Python RegEx пропускает первые несколько символов? - PullRequest
1 голос
/ 25 октября 2009

Эй, у меня довольно простой вопрос о регулярных выражениях. Я хочу просто вернуть текст внутри (и включая) теги body, и я знаю, что следующее неверно, поскольку оно также будет соответствовать всем символам перед открывающим тегом body. Мне было интересно, как бы вы пропустили это?

x = re.match('(.*<body).*?(</body>)', fileString)

Спасибо! * * 1004

Ответы [ 6 ]

9 голосов
/ 25 октября 2009

Я не знаю Python, но вот быстрый пример, собранный вместе с использованием Beautiful Soup , который я часто вижу рекомендованным для анализа Python HTML.

import BeautifulSoup

soup = BeautifulSoup(fileString)

bodyTag = soup.html.body.string

Это будет (в теории) иметь дело со всеми сложностями HTML, что очень сложно с чисто основанными на регулярных выражениях ответами, потому что это не то, для чего было разработано регулярное выражение.

2 голосов
/ 25 октября 2009

Вот пример кода, который использует регулярное выражение, чтобы найти весь текст между тегами <body>...</body>. Хотя это демонстрирует некоторые возможности модуля re python, обратите внимание, что модуль Beautiful Soup очень прост в использовании и является лучшим инструментом, если вы планируете анализ HTML или XML. (См. Ниже пример того, как вы можете разобрать это с помощью BeautifulSoup.)

#!/usr/bin/env python
import re

# Here we have a string with a multiline <body>...</body>
fileString='''baz<body>foo
baby foo
baby foo
baby foo
</body><body>bar</body>'''

# re.DOTALL tells re that '.' should match any character, including newlines.
x = re.search('(<body>.*?</body>)', fileString, re.DOTALL)
for match in x.groups():
    print(match)
# <body>foo
# baby foo
# baby foo
# baby foo
# </body>

Если вы хотите собрать все совпадения, вы можете использовать re.findall:

print(re.findall('(<body>.*?</body>)', fileString, re.DOTALL))
# ['<body>foo\nbaby foo\nbaby foo\nbaby foo\n</body>', '<body>bar</body>']

и если вы планируете использовать этот шаблон более одного раза, вы можете предварительно скомпилировать его:

pat=re.compile('(<body>.*?</body>)', re.DOTALL)
print(pat.findall(fileString))
# ['<body>foo\nbaby foo\nbaby foo\nbaby foo\n</body>', '<body>bar</body>']

А вот как вы могли бы сделать это с BeautifulSoup:

#!/usr/bin/env python
from BeautifulSoup import BeautifulSoup

fileString='''baz<body>foo
baby foo
baby foo
baby foo
</body><body>bar</body>'''
soup = BeautifulSoup(fileString)
print(soup.body)
# <body>foo
# baby foo
# baby foo
# baby foo
# </body>

print(soup.findAll('body'))
# [<body>foo
# baby foo
# baby foo
# baby foo
# </body>, <body>bar</body>]
0 голосов
/ 25 октября 2009

Вы не можете разобрать HTML с регулярным выражением. HTML не является обычным языком. Вместо этого используйте HTML-анализатор, такой как lxml.

0 голосов
/ 25 октября 2009

Содержит ли ваша fileString несколько строк ? В этом случае вам может потребоваться указать его или пропустить строки явно:

x = re.match(r"(?:.|\n)*(<body>(?:.|\n)*</body>)", fileString)

или, проще, с модулем re:

x = re.match(r".*(<body>.*</body>)", fileString, re.DOTALL)

x.groups()[0] должен содержать вашу строку, если x не None.

0 голосов
/ 25 октября 2009
x = re.search('(<body>.*</body>)', fileString)
x.group(1)

Меньше печатать, чем ответы на вопросы

0 голосов
/ 25 октября 2009
 x = re.match('.*(<body>.*?</body>)', fileString)

Рассмотрим минидом для разбора HTML.

...