7

我希望这个问题不是 RTFM 问题。我正在尝试编写一个从标准 HTML 网页(<link href...标签)中提取链接的 Python 脚本。我在网上搜索了匹配的正则表达式,发现了许多不同的模式。是否有任何商定的标准正则表达式来匹配链接?

亚当

更新: 我实际上正在寻找两个不同的答案:

  1. 什么是解析 HTML 链接的库解决方案。Beautiful Soup似乎是一个很好的解决方案(谢谢Igal Serbancletus
  2. 可以使用正则表达式定义链接​​吗?
4

8 回答 8

17

带有 HTML 的正则表达式变得混乱。只需使用像 Beautiful Soup 这样的 DOM 解析器。

于 2009-01-10T13:52:47.753 回答
8

正如其他人所建议的那样,如果不需要类似实时的性能,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,则可以使用(快得多)像 expat 这样的 XML 解析器。

正则表达式,由于上述原因(解析器必须保持状态,而正则表达式不能做到这一点)永远不会是一个通用的解决方案。

于 2009-01-10T17:53:02.963 回答
5

不,没有。

您可以考虑使用Beautiful Soup。您可以将其称为解析 html 文件的标准。

于 2009-01-10T13:53:19.797 回答
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,则存在一百万种格式错误的可能性。

如果您知道并且可以依赖目标页面的确切输出格式,则可以使用正则表达式。否则,它是完全错误的抓取网页的选择。

于 2009-01-10T15:10:23.387 回答
3

链接不应该是定义明确的正则表达式吗?这是一个比较理论的问题,

我第二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 是一种上下文无关语法,而不是常规语言。

于 2009-01-10T15:50:51.307 回答
1

这在一定程度上取决于 HTML 的生成方式。如果它受到一定程度的控制,您可以逃脱:

re.findall(r'''<link\s+.*?href=['"](.*?)['"].*?(?:</link|/)>''', html, re.I)
于 2009-01-10T14:19:18.620 回答
1

在那里回答你的两个子问题。

  1. 我有时将 SGMLParser 子类化(包含在核心 Python 发行版中)并且必须说它是直截了当的。
  2. 我认为 HTML 不适合“定义明确的”正则表达式,因为它不是常规语言。
于 2009-01-10T14:24:30.467 回答
0

针对问题 #2(链接不应该是定义明确的正则表达式),答案是……不。

HTML 链接结构是递归的,很像编程语言中的括号和大括号。必须有相同数量的开始和结束构造,并且“链接”表达式可以嵌套在其自身中。

要正确匹配“链接”表达式,需要正则表达式来计算开始和结束标签。正则表达式是有限自动机的一类。根据定义,有限自动机不能“计数”模式中的构造。需要语法来描述这样的递归数据结构。正则表达式无法“计数”这就是为什么您会看到用语法描述的编程语言而不是正则表达式。

因此,不可能创建一个 100% 正则匹配所有“链接”表达式的正则表达式。当然,有一些正则表达式可以匹配大量的“链接”,并且准确度很高,但它们永远不会完美。

我最近写了一篇关于这个问题的博客文章。 正则表达式限制

于 2009-01-10T15:48:48.423 回答