Regex для ссылок в html-тексте
Надеюсь, этот вопрос не является RTFM.
Я пытаюсь написать Python script, который извлекает ссылки со стандартной HTML-страницы (теги <link href...
).
Я искал в Интернете для соответствия regexen и нашел много разных шаблонов. Есть ли согласованное стандартное регулярное выражение для соответствия ссылкам?
Адам
UPDATE:
Я действительно ищу два разных ответа:
- Что такое библиотечное решение для синтаксического анализа ссылок HTML. Beautiful Soup кажется хорошим решением (спасибо,
Igal Serban
и cletus
!)
- Можно ли определить ссылку с помощью регулярного выражения?
Ответы
Ответ 1
Как показали другие, если производительность в режиме реального времени не требуется, BeautifulSoup является хорошим решением:
import urllib2
from BeautifulSoup import BeautifulSoup
html = urllib2.urlopen("http://www.google.com").read()
soup = BeautifulSoup(html)
all_links = soup.findAll("a")
Что касается второго вопроса, да, ссылки HTML должны быть четко определены, но HTML, с которым вы действительно сталкиваетесь, вряд ли будет стандартным. Красота BeautifulSoup заключается в том, что она использует эвристику, подобную браузеру, для того, чтобы попытаться проанализировать нестандартный, искаженный HTML-код, с которым вы, вероятно, столкнетесь.
Если вы уверены, что работаете над стандартным XHTML, вы можете использовать (намного) более быстрые XML-парсеры, такие как expat.
Regex, по причинам выше (синтаксический анализатор должен поддерживать состояние, а регулярное выражение не может этого сделать) никогда не будет общим решением.
Ответ 2
Регулярные выражения с HTML становятся беспорядочными. Просто используйте парсер DOM, например Beautiful Soup.
Ответ 3
Нет. Нет.
Вы можете использовать Beautiful Soup. Вы можете назвать это стандартом для разбора html файлов.
Ответ 4
Неправильно ли ссылка будет четко определенным регулярным выражением?
Нет, [X] HTML не находится в анализе общего случая с регулярным выражением. Рассмотрим примеры, например:
<link title='hello">world' href="x">link</link>
<!-- <link href="x">not a link</link> -->
<![CDATA[ ><link href="x">not a link</link> ]]>
<script>document.write('<link href="x">not a link</link>')</script>
и что всего несколько случайных действительных примеров; если вам нужно справиться с реальным HTML-супом HTML, существует миллион искаженных возможностей.
Если вы знаете и можете полагаться на точный формат вывода целевой страницы, вы можете уйти с регулярным выражением. В противном случае это совершенно неправильный выбор для очистки веб-страниц.
Ответ 5
Не будет ли ссылка корректным регулярным выражением? Это довольно теоретический вопрос,
Второй ответ PEZ:
Я не думаю, что HTML поддается "хорошо определенным" регулярным выражениям, поскольку он не является обычным языком.
Насколько я знаю, любой тег HTML может содержать любое количество вложенных тегов. Например:
<a href="http://stackoverflow.com">stackoverflow</a>
<a href="http://stackoverflow.com"><i>stackoverflow</i></a>
<a href="http://stackoverflow.com"><b><i>stackoverflow</i></b></a>
...
Таким образом, в принципе, чтобы правильно соответствовать тегу, вы должны иметь возможность, по крайней мере, соответствовать строкам формы:
BE
BBEE
BBBEEE
...
BBBBBBBBBBEEEEEEEEEE
...
где B означает начало тега, а E означает конец. То есть вы должны иметь возможность сопоставлять строки, образованные любым числом B, за которым следует такое же количество E. Для этого ваш собеседник должен иметь возможность "подсчитывать", а регулярные выражения (т.е. Автоматы с конечным состоянием) просто не могут этого сделать (для подсчета автомата требуется хотя бы стек). Ссылаясь на ответ PEZ, HTML - это контекстно-свободная грамматика, а не обычный язык.
Ответ 6
Это немного зависит от того, как создается HTML. Если он несколько контролируется, вы можете сойти с рук:
re.findall(r'''<link\s+.*?href=['"](.*?)['"].*?(?:</link|/)>''', html, re.I)
Ответ 7
Отвечая на ваши два подзапроса там.
- Я иногда подклассифицировал SGMLParser (входит в основной дистрибутив Python) и должен сказать это прямо.
- Я не думаю, что HTML поддается "хорошо определенным" регулярным выражениям, поскольку он не является обычным языком.
Ответ 8
В ответ на вопрос № 2 (не должна быть ссылка, которая является четко определенным регулярным выражением) ответ... нет.
Структура ссылок HTML является рекурсивной, такой как parens и фигурные скобки в языках программирования. Должно быть одинаковое количество начальных и конечных конструкций, а выражение "link" может быть вложено внутри себя.
Чтобы правильно сопоставить выражение "ссылка", для вычисления начальных и конечных тегов потребуется регулярное выражение. Регулярные выражения - это класс конечных автоматов. По определению конечные автоматы не могут "подсчитывать" конструкции внутри шаблона. Для описания рекурсивной структуры данных, такой как эта, требуется грамматика. Неспособность регулярного выражения "подсчитывать" - это то, почему вы видите языки программирования, описанные в Grammars, в отличие от регулярных выражений.
Таким образом, невозможно создать регулярное выражение, которое положительно соответствует 100% всех выражений "link". Есть, конечно, регулярное выражение, которое будет соответствовать большому количеству "ссылок" с высокой степенью точности, но они никогда не будут идеальными.
Недавно я написал статью в блоге об этой проблеме. Ограничения регулярного выражения