2010-08-13 3 views
0

Мне нужно регулярное выражение, которое соответствуетрегулярное выражение, которое соответствует строке, которая содержит текст

re.compile('userpage') 


href="www.example.com?u=userpage&as=233&p=1" 
href="www.example.com?u=userpage&as=233&p=2" 

Я хочу, чтобы все адреса, которые имеют и = userpage и р = 1

Как я могу изменить регулярное выражение выше, чтобы найти u = userpage и p = 1?

+2

это как если бы вы сказали * Я хотел бы выйти. Как я прыгаю из окна должным образом, чтобы не сломать ногу? *, Когда лучший подход - использовать вашу дверь. Тем не менее, всегда есть больше способов, как это сделать .. – mykhal

ответ

0

/((u=userpage).*?(p=1))|((p=1).*?(u=userpage))/

Это позволит получить все строки, содержащие два бита, которые вы ищете.

+0

уродливый и неэффективный, но, возможно, рабочий :) Кстати, я бы ввел '\>' после 'p = 1' – mykhal

+0

@mykhal, тогда вы получите непригодный RE (так как это не то, что Python RE используют для указания границы слов - существует много диалектов RE, и я думаю, что вы думаете о том, например, vim's). Если вы использовали вместо '\ b', как и в моем ответе, у вас не было бы этой проблемы (поскольку это _is_, что Python RE используют для этой цели ;-). –

+0

@Alex Martelli, у вас все еще есть проблемы. См. Мой комментарий к вашему ответу. – habnabit

0

Чтобы убедиться, что вы случайно не соответствуют части как bu=userpage, u=userpagezap, p=111 или zap=1, вам необходимо обильное использование \b «слово-граничном» RE шаблон элемента. Т.е .:

re.compile(r'\bp=1\b.*\bu=userpage\b|\bu=userpage\b.*\bp=1\b') 

Слово-граничных элементов в рисунке RE предотвращают вышеупомянутые, по-видимому, нежелательные «случайных» совпадений. Конечно, если в вашем заявлении они не «нежелательно», то есть, если вы положительно хотите в соответствии с p=123 и т. П., Вы можете легко удалить некоторые или все элементы, расположенные выше! -)

+0

+1 Забыл о частичных матчах. – NullUserException

+1

'\ b' не защищает вас от всего. Ваш код по-прежнему разбивается на '? U = userpage% 20whatever'. – habnabit

+0

@Aaron, true,% -escapes вводят слово-границу. Если вам нужно защитить от этого, '(\? \ \ &) 'Как« начало слова »и' (\ & | $) 'как« конец слова »может служить вам лучше (или, если вам не нужна переносимость версий Python , вы можете использовать 'parse_qs', если вы можете правильно догадаться, в каком модуле он находится, в различных версиях интереса ;-). –

4
import lxml.html, urlparse 

d = lxml.html.parse(...) 
for link in d.xpath('//a/@href'): 
    url = urlparse.urlparse(link) 
    if not url.query: 
     continue 
    params = urlparse.parse_qs(url.query) 
    if 'userpage' in params.get('u', []) and '1' in params.get('p', []): 
     print link 
+0

+1 хороший ответ. – nosklo

-1

Это можно сделать с помощью взлома строки, но вы не должны. Уже в стандартной библиотеке:

>>> import urllib.parse 
>>> urllib.parse.parse_qs("u=userpage&as=233&p=1") 
{'u': ['userpage'], 'as': ['233'], 'p': ['1']} 

и, следовательно,

import urllib.parse 
def filtered_urls(urls): 
    for url in urls: 
     try: 
      attrs = urllib.parse.parse_qs(url.split("?")[ 1 ]) 
     except IndexError: 
      continue 

     if "userpage" in attrs.get("u", "") and "1" in attrs.get("p", ""): 
      yield url 

foo = [ "www.example.com?u=userpage&as=233&p=1", "www.example.com?u=userpage&as=233&p=2" ] 

print(list(filtered_urls(foo))) 

Обратите внимание, что это Python 3 - в Python parse_qs находится в urlparse вместо.

+0

Возникает синтаксический эффект и «пользовательская страница»! = ['Userpage'] '. Кроме того, почему бы не urlparse.urlparse получить запрос из URL? – habnabit

+0

Правда, но довольно тривиальный (= для ==). Забыл о списках, хотя, спасибо. И 'urlparse' в порядке, но overkill, если мы просто хотим строку запроса. – katrielalex

+2

'TypeError: аргумент типа 'NoneType' не является итерабельным'; вы не можете делать 'in' on' None'. Пожалуйста, попробуйте * ваше решение, прежде чем публиковать его. – habnabit

5

, если вы хотите использовать, на мой взгляд, что-то более правильный подход, чем регулярное выражение:

from urlparse import * 
urlparsed = urlparse('www.example.com?u=userpage&as=233&p=1') 
# -> ParseResult(scheme='', netloc='', path='www.example.com', params='', query='u=userpage&as=233&p=1', fragment='') 
qdict = dict(parse_qsl(urlparsed.query)) 
# -> {'as': '233', 'p': '1', 'u': 'userpage'} 
qdict.get('p') == '1' and qdict.get('u') == 'userpage' 
# -> True 
+0

Ugh. 'import *'. = p – katrielalex

+0

@katrielalex, что вы еще не видели? :) btw, изначально это было: 'from urlparse import urlparse, parse_qsl', но я сократил его ради удобочитаемости (это не ключевая часть, а' from urlparse import urlparse' тоже не очень эстетично) – mykhal

+0

Хех, я знаю , не волнуйся. Это всего лишь одна из таких вещей, как «не анализировать HTML с регулярным выражением», которые приходят сюда очень ужасно. = p – katrielalex

2

Regex не является хорошим выбором для этого, потому что 1) Титулы могут появиться в любом порядке, и 2) вам нужно выполнить дополнительные проверки для разделителей запросов, чтобы вы не соответствовали потенциальным таким странностям, как «flu = userpage», «sp = 1», «u = userpage% 20haha» или «s = 123». (Примечание: Я пропустил два из этих случаев на моем первом проходе! Так же были и другие.) Также: 3) у вас уже есть хорошая библиотека синтаксического анализа URL в Python, которая выполняет эту работу за вас.

с регулярным выражением вам нужно что-то неуклюжее, как:

q = re.compile(r'([?&]u=userpage&(.*&)?p=1(&|$))|([?&]p=1&(.*&)?u=userpage(&|$))') 
return q.search(href) is not None 

С urlparse вы можете сделать это. urlparse дает вам немного больше, чем вы хотите, но вы можете использовать вспомогательную функцию, чтобы результат был простым:

def has_qparam(qs, key, value): 
    return value in qs.get(key, []) 

qs = urlparse.parse_qs(urlparse.urlparse(href).query) 
return has_qparam(qs, 'u', 'userpage') and has_qparam(qs, 'p', '1') 
+0

те 'qs ['u'] == 'userpage'' не будут работать, потому что' parse_qs' dict имеет значения списка .. может быть тогда '' userpage' в qs ['u'] '.. или используйте 'parse_qsl' (tuple) и конвертируйте в dict – mykhal

+0

А, да, это тоже помогло мне в прошлом: -P. Исправлена. –

Смежные вопросы