Требуется помощь в регулярных выражениях Python

1

Мне нужно получить информацию с веб-сайта, который выводит его между <font color="red">needed-info-here</font> OR <span style="font-weight:bold;">needed-info-here</span>, случайным образом.

Я могу получить его, когда я использую

start = '<font color="red">'
end = '</font>'
expression = start + '(.*?)' + end
match = re.compile(expression).search(web_source_code)
needed_info = match.group(1)

но тогда мне нужно выбрать, чтобы получить либо <font>, либо <span>, при неудаче, когда сайт использует другой тег.

Как изменить регулярное выражение, чтобы оно всегда было успешным?

  • 6
    «Каждый раз, когда вы пытаетесь анализировать HTML с помощью регулярных выражений, нечестивый ребенок плачет кровью девственниц, а русские хакеры набивают ваше веб-приложение».
  • 3
    Когда все говорят, что вы не должны использовать re с html, лучше послушать. Больше не буду делать это с новыми проектами. :) Попробуйте предложенные решения сейчас.
Теги:

6 ответов

3
Лучший ответ

Вы можете присоединиться к двум альтернативам с вертикальной полосой:

start = '<font color="red">|<span style="font-weight:bold;">'
end = '</font>|</span>'

поскольку вы знаете, что тег шрифта всегда будет закрыт </font>, тег span всегда на </span>.

Однако рассмотрите также использование твердого синтаксического анализатора HTML, такого как BeautifulSoup, вместо того, чтобы сворачивать ваши собственные регулярные выражения, для синтаксического анализа HTML, что особенно непригодно в целом для получения синтаксического анализа регулярными выражениями.

  • 0
    Спасибо, это работает.
  • 0
    +1 в отличии от моего, на самом деле полезный ответ =)
7

Не анализировать HTML с регулярным выражением.

Regex - неправильный инструмент для использования для этой проблемы. Посмотрите BeautifulSoup или lxml.

  • 1
    ах - я люблю это.
1
expression = '(<font color="red">(.*?)</font>|<span style="font-weight:bold;">(.*?)</span>)'
match = re.compile(expression).search(web_source_code)
needed_info = match.group(2)

Это выполнит эту работу, но вы не должны использовать regex для анализа html

1

Хотя регулярные выражения не являются лучшим выбором для синтаксического анализа HTML.

Для образования, вот возможный ответ на ваш вопрос:

start = '<(?P<tag>font|tag) color="red">'
end = '</(?P=tag)>'
expression = start + '(.*?)' + end
1

Regex и HTML не так хороши, HTML имеет слишком много потенциальных вариаций, которые будут вызывать ваше регулярное выражение. BeautifulSoup - это стандартный инструмент для использования здесь, но я считаю, что pyparsing может быть столь же эффективным, а иногда даже проще создавать при попытке найти конкретный тег относительно определенного предыдущего тега.

Вот как решить свой вопрос, используя pyparsing:

html = """ need to get info from a website that outputs it between <font color="red">needed-info-here</font> OR <span style="font-weight:bold;">needed-info-here</span>, randomly.
<font color="white">but not this info</font> and 
<span style="font-weight:normal;">dont want this either</span>
"""

from pyparsing import *

font,fontEnd = makeHTMLTags("FONT")
# only match <font> tags with color="red"
font.setParseAction(withAttribute(color="red"))
# only match <span> tags with given style
span,spanEnd = makeHTMLTags("SPAN")
span.setParseAction(withAttribute(style="font-weight:bold;"))

# define full match patterns, define "body" results name for easy access
fontpattern = font + SkipTo(fontEnd)("body") + fontEnd
spanpattern = span + SkipTo(spanEnd)("body") + spanEnd

# now create a single pattern, matching either of the other patterns
searchpattern = fontpattern | spanpattern

# call searchString, and extract body element from each match
for text in searchpattern.searchString(html):
    print text.body

Печать

needed-info-here
needed-info-here
0

Я не использовал Python, но если вы делаете выражения равными следующим, он должен работать:

/(?P<open><(font|span)[^>]*>)(?P<info>[^<]+)(?P<close><\/(font|span)>)/gi

Затем просто получите доступ к вашей необходимой информации с именем "info".

PS - Я также соглашаюсь с правилом "не разобрав HTML с регулярным выражением", но если вы знаете, что он появится либо в тегах шрифта, либо в тегах span, то пусть будет так...

Кроме того, зачем использовать тег шрифта? Я не использовал тег шрифта, так как я узнал CSS.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню