Хорошо, поэтому я работаю над регулярным выражением для поиска всей информации заголовка на сайте.
Я скомпилировал регулярное выражение:
regex = re.compile(r'''
<h[0-9]>\s?
(<a[ ]href = "[A-Za-z0-9.]*">)?\s?
[A-Za-z0-9.,:'"=/?;\s]*\s?
[A-Za-z0-9.,:'"=/?;\s]?
''', re.X)
Когда я запускаю это в python reg ex. тестером, отлично работает.
Пример данных:
<body>
<h1>Dog </h1>
<h2>Cat </h2>
<h3>Fancy </h3>
<h1>Tall cup of lemons</h1>
<h1><a href = "dog.com">Dog thing</a></h1>
</body>
Теперь в REDemo это прекрасно работает.
Однако когда я помещаю его в свой код Python, он печатает только <a href = "dog.com">
Вот мой код на Python, я не уверен, что я делаю что-то не так или что-то потеряно при переводе. Я ценю вашу помощь.
stories=[]
response = urllib2.urlopen('http://apricotclub.org/duh.html')
html = response.read().lower()
p = re.compile('<h[0-9]>\s?(<a href=\"[A-Za-z0-9.]*\">)?\s?[A-Za-z0-9.,:\'\"=/?;\s]*\s?[A-Za-z0-9.,:\'\"=/?;\s]?')
stories=re.findall(p, html)
for i in stories:
if len(i) >= 5:
print i
Я также должен отметить, что когда я извлекаю (<a href=\"[A-Za-z0-9.]*\">)? из регулярного выражения, он отлично работает для несвязанных строк <hN>.






Парсинг с помощью регулярных выражений работает и для обычных языков. HTML - это не обычный язык, и то, что вы сейчас находите на веб-страницах, - это полная чушь. BeautifulSoup имеет дело с HTML-супом из тегов с эвристикой, подобной браузеру, поэтому вы получаете проанализированный HTML, который напоминает то, что отображает браузер.
Обратной стороной является не очень быстрая работа. Есть lxml для синтаксического анализа правильно сформированного html, но вам действительно стоит использовать BeautifulSoup, если вы не на 100% уверены, что ваш ввод всегда будет правильно сформирован.
Из-за фигурных скобок вокруг тега привязки эта часть интерпретируется как группа захвата. Это приводит к возврату только группы захвата, а не всего совпадения регулярного выражения.
Поместите все регулярное выражение в фигурные скобки, и вы увидите, что правильные совпадения отображаются как первый элемент в возвращаемых кортежах.
Но действительно, вам стоит использовать настоящий парсер.
Этот вопрос задавали в нескольких формах за последние несколько дней, поэтому я собираюсь сказать это очень четко.
Используйте BeautifulSoup, html5lib или lxml.html. Пожалуйста.
@Jerub: Я согласен с вашим ответом, но он не отвечает на вопрос OP. Представьте, что вы не можете использовать BeautifulSoup, html5lib, lxml, а ваши html-файлы просто очень, тогда будет достаточно тривиального регулярного выражения.
Как уже упоминалось, вы должны использовать синтаксический анализатор вместо регулярного выражения.
Вот как вы могли бы сделать это с помощью регулярного выражения:
import re
html = '''
<body>
<h1>Dog </h1>
<h2>Cat </h2>
<h3>Fancy </h3>
<h1>Tall cup of lemons</h1>
<h1><a href = "dog.com">Dog thing</a></h1>
</body>
'''
p = re.compile(r'''
<(?P<header>h[0-9])> # store header tag for later use
\s* # zero or more whitespace
(<a\shref = "(?P<href>.*?)">)? # optional link tag. store href portion
\s*
(?P<title>.*?) # title
\s*
(</a>)? # optional closing link tag
\s*
</(?P=header)> # must match opening header tag
''', re.IGNORECASE + re.VERBOSE)
stories = p.finditer(html)
for match in stories:
print '%(title)s [%(href)s]' % match.groupdict()
Вот пара хороших ресурсов по регулярным выражениям:
Регулярное выражение не работает для заголовков со ссылками. И OP спрашивает конкретно о заголовках ссылок с.
Основываясь на ответах на данный момент:
Лучше всего использовать движок синтаксического анализа. Он может охватывать множество случаев и элегантно. Я пробовал BeautifulSoup, и он мне очень нравится. Также прост в использовании, с отличным учебником.
Если иногда кажется, что стреляют мухи из пушки, вы можете использовать регулярное выражение для быстрого анализа. Если это то, что вам нужно, вот что вам нужно, так это модифицированный код, который будет перехватывать все заголовки (даже те, которые занимают несколько строк):
p = re.compile(r'<(h[0-9])>(.+?)</>', re.IGNORECASE | re.DOTALL)
stories = re.findall(p, html)
for i in stories:
print i
i в ваших случаях - это кортеж, например. ('h1', '<a href="dog.com"> Собака </a>')
Я использовал beautifulsoup для синтаксического анализа желаемого HTML. У меня есть указанный выше HTML-код в файл с именем foo.html, который позже читается как файловый объект.
from BeautifulSoup import BeautifulSoup
H_TAGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
def extract_data():
"""Extract the data from all headers
in a HTML page."""
f = open('foo.html', 'r+')
html = f.read()
soup = BeautifulSoup(html)
headers = [soup.findAll(h) for h in H_TAGS if soup.findAll(h)]
lst = []
for x in headers:
for y in x:
if y.string:
lst.append(y.string)
else:
lst.append(y.contents[0].string)
return lst
Вышеупомянутая функция возвращает:
>>> [u'Dog ', u'Tall cup of lemons', u'Dog thing', u'Cat ', u'Fancy ']
Вы можете добавить любое количество тегов заголовков в список h_tags. Я принял все заголовки. Если вы можете легко решать проблемы с помощью BeautifulSoup, то лучше его использовать. :)
Не забывайте, что html5lib также может анализировать несоответствующие документы в разумную структуру.