Python: хранить много совпадений регулярных выражений в кортеже? - PullRequest
4 голосов
/ 25 марта 2012

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

Допустим, у меня есть страница со следующим, сохраненным в переменной HTMLtext:

<ul>
<li class="active"><b><a href="/blog/home">Back to the index</a></b></li>
<li><b><a href="/blog/about">About Me!</a></b></li>
<li><b><a href="/blog/music">Audio Production</a></b></li>
<li><b><a href="/blog/photos">Gallery</a></b></li>
<li><b><a href="/blog/stuff">Misc</a></b></li>
<li><b><a href="/blog/contact">Shoot me an email</a></b></li>
</ul>

Я хочу выполнить поиск по регулярному выражению по этому тексту и вернуть кортеж, содержащий последний URL-каталог каждой ссылки.Итак, я хотел бы вернуть что-то вроде этого:

pages = ["home", "about", "music", "photos", "stuff", "contact"]

Пока что я могу использовать регулярные выражения для поиска одного результата:

pages = [re.compile('<a href="/blog/(.*)">').search(HTMLtext).group(1)]

Запускэто выражение составляет pages = ['home'].

Как я могу продолжить поиск по регулярному выражению для всего текста, добавив соответствующий текст к этому кортежу?

(Примечание: Я знаю, что, вероятно, НЕ следует использовать регулярное выражение для разбора HTML . Но я все равно хочу знать, как это сделать.)

Ответы [ 5 ]

2 голосов
/ 25 марта 2012

Ваш шаблон не будет работать на всех входах, включая ваш. .* будет слишком жадным (технически он находит максимальное совпадение), в результате чего он будет первым href и последним соответствующим закрытием. Два самых простых способа исправить это - использовать либо минимальное совпадение, либо класс отрицательных символов.

# minimal match approach
pages = re.findall(r'<a\s+href="/blog/(.+?)">', 
                   full_html_text, re.I + re.S)

# negated charclass approach
pages = re.findall(r'<a\s+href="/blog/([^"]+)">',
                   full_html_text, re.I)

Обязательное предупреждение

Для простого и достаточно хорошо ограниченного текста регулярные выражения просто хороши; в конце концов, именно поэтому мы используем регулярное выражение поиска и замены в наших текстовых редакторах при редактировании HTML! Однако, чем меньше вы знаете о входных данных, тем сложнее становится, например,

  • если между <a и href есть какое-то другое поле, например <a title="foo" href="bar">
  • проблемы с корпусом, такие как <A HREF='foo'>
  • проблемы с пробелами
  • альтернативные кавычки, такие как href='/foo/bar' вместо href="/foo/bar"
  • встроенные комментарии HTML

Это не исключительный список проблем; Есть и другие. Итак, использование регулярных выражений в HTML, таким образом, возможно , но целесообразность зависит от слишком многих других факторов, чтобы судить.

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

2 голосов
/ 25 марта 2012

Использование findall функция re модуля:

pages = re.findall('<a href="/blog/([^"]*)">',HTMLtext)
print(pages)

Выход:

['home', 'about', 'music', 'photos', 'stuff', 'contact']
1 голос
/ 25 марта 2012

Чтобы найти все результаты, используйте findall().Также вам нужно скомпилировать re только один раз, а затем вы можете использовать его снова.

1 голос
/ 25 марта 2012

Функция re.findall () и функция re.finditer () используются для поиска нескольких совпадений.

1 голос
/ 25 марта 2012

Используйте findall вместо search:

>>> pages = re.compile('<a href="/blog/(.*)">').findall(HTMLtext)
>>> pages
['home', 'about', 'music', 'photos', 'stuff', 'contact']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...