Regex попробуйте и сопоставьте, пока не достигнете конечного тега в python - PullRequest
0 голосов
/ 14 февраля 2010

Мне нужна помощь с регулярным выражением в python, и Google подводит меня. По сути, я ищу какой-то html и есть определенный тип таблицы, которую я ищу, особенно любая таблица, которая включает в себя фоновый тег (то есть BGCOLOR). Некоторые таблицы имеют этот тег, а некоторые нет. Может ли кто-нибудь помочь мне с тем, как написать регулярное выражение, которое ищет начало таблицы, затем ищет BGCOLOR, но если оно достигает конца таблицы, то оно останавливается и движется дальше?

Вот очень упрощенный пример, который будет служить цели сервера:

`<TABLE>
<B>Item 1.</B>
</TABLE>

<TABLE>
BGCOLOR
</TABLE>

<TABLE>
<B>Item 2.</B>
</TABLE>`

Итак, у нас есть три таблицы, но я заинтересован только в поиске средней таблицы, содержащей BGCOLOR На данный момент проблема с моим регулярным выражением состоит в том, что он ищет начальный тег таблицы, затем ищет «BGCOLOR» и ему все равно, передает ли он конечный тег таблицы:

tables = re.findall('\<table.*?BGCOLOR=".*?".*?\<\/table\>', text, re.I|re.S)

Таким образом, он найдет первые две таблицы, а не только вторую таблицу. Дайте мне знать, если кто-нибудь знает, как справиться с этой ситуацией.

Спасибо, Michael

Ответы [ 4 ]

4 голосов
/ 14 февраля 2010

Не используйте регулярные выражения для разбора HTML. Используйте lxml или BeautifulSoup.

3 голосов
/ 14 февраля 2010

Не используйте регулярные выражения для разбора HTML - используйте анализатор HTML, например BeautifulSoup .

В частности, ваша ситуация в основном заключается в том, что вам приходится иметь дело с «вложенными скобками» (где открытое «parens» - это открывающий тег <table>, а соответствующие закрытые parens - это совпадающее </table>) - именно такой разбор задач, которые регулярные выражения не могут выполнять хорошо. Большая часть работы по синтаксическому анализу HTML точно связана с этой проблемой «совпавших скобок», которая делает регулярные выражения совершенно ужасным выбором для этой цели.

Вы упоминаете в комментарии к другому ответу, что у вас были неопределенные проблемы с BS - я подозреваю, что вы пробовали последнюю версию 3.1 (которая пошла под откос) вместо правильной; вместо этого попробуйте 3.0.8, как рекомендует собственная документация BS , и вам будет лучше.

Если вы заключили какой-то договор с Злом, чтобы никогда не использовать подходящий инструмент для работы, ваша задача может быть не полностью невозможной, если вам не нужно иметь дело с вложением (просто соответствуя ), то есть никогда не будет таблицы внутри другой таблицы. В этом случае вы можете идентифицировать одну таблицу с r'<\s*TABLE(.*?)<\s*/\s*TABLE' (с подходящими флагами, такими как re.DOTALL и re.I); цикл по всем таким совпадениям с помощью метода регулярных выражений finditer; и в теле цикла проверьте, находится ли BGCOLOR (без учета регистра) внутри тела текущего совпадения. Это все еще будет более хрупким и более трудоемким, чем использование парсера HTML, но, хотя это определенно плохой выбор, это не должно быть отчаянной ситуацией.

Если у вас do есть вложенные таблицы, с которыми нужно бороться, тогда - это отчаянная ситуация.

0 голосов
/ 14 февраля 2010

Вот код, который закончил работать на меня. Он находит правильную таблицу и добавляет вокруг нее больше тегов, чтобы ее можно было идентифицировать из группы с открытыми и закрытыми тегами realTable.

soup = BeautifulSoup(''.join(text))
for p in soup.findAll('table'):
    pattern = '.*BGCOLOR.*'
    if (re.match(pattern, str(p), re.S|re.I)):
        tags = Tag(soup, "realTable")
        p.replaceWith(tags)
        text = NavigableString(str(p))
        tags.insert(0, text)
print soup

распечатывает это:

<table><b>Item 1.</b></table>
<realTable><table>blah BGCOLOR blah</table></realTable>
<table><b>Item 2.</b></table>
0 голосов
/ 14 февраля 2010

если ваша задача просто так, вот способ. разделите на <TABLE>, затем итерируйте элементы и найдите нужный шаблон.

myhtml="""
<TABLE>
<B>Item 1.</B>
</TABLE>

some text1
some text2
some text3

<TABLE>
blah
BGCOLOR
blah
</TABLE>

some texet
<TABLE>
<B>Item 2.</B>
</TABLE>
"""

for tab in myhtml.split("</TABLE>"):
    if "<TABLE>" in tab and "BGCOLOR" in tab:
        print ''.join(tab.split("<TABLE>")[1:])

выход

$ ./python.py

blah
BGCOLOR
blah
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...