从HTML链接中提取URL的正则表达式

38

我是Python的新手,正在学习正则表达式,但我需要帮助。

下面是HTML源代码:

<a href="http://www.ptop.se" target="_blank">http://www.ptop.se</a>

我正在尝试编写一个工具,仅打印出 http://ptop.se。请帮我一下吗?


2
请使用正则表达式在HTML文本中匹配链接。 - S.Lott
6
我已经离开 Stack Overflow 有一段时间了,很高兴看到我没有错过什么,人们仍然每天死活想要用正则表达式解析 HTML。 - bobince
2
多次一天,情况非常糟糕,我创建了两个问题和一个表单答案,以便将人们重定向到那里。 - Chas. Owens
10个回答

86

如果你只需要一个:

import re
match = re.search(r'href=[\'"]?([^\'" >]+)', s)
if match:
    print(match.group(1))

如果你有一个长字符串,并且想要在其中找到每个匹配的模式:

import re
urls = re.findall(r'href=[\'"]?([^\'" >]+)', s)
print(', '.join(urls))

在这里,s 是你要搜索匹配的字符串。

正则表达式部分的快速解释:

r'...' 是一个“原始”字符串。它不需要像普通字符串一样担心转义字符(尤其是 \)。在原始字符串中,一个 \ 就是一个 \。而在普通字符串中,每次都需要写成 \\,这会很困难。

"href=[\'"]?" 表示匹配 "href=",后面可能跟着一个 '"。因为无法确定 HTML 的确切格式,引号不是必需的。

接下来的内容用 "()" 包裹,表示将其作为一个“组”处理,也就是说我们可以将其单独提取出来。这只是一种说“这就是我感兴趣的模式部分”的方法。

"[^\'" >]+" 表示匹配任何不包含 '"> 或空格的字符。本质上,这是 URL 的结尾字符列表。这让我们避免了试图编写可靠匹配完整 URL 的正则表达式,这可能会有些复杂。

另一个答案中使用 BeautifulSoup 的建议不错,但这确实引入了更高级的外部要求。此外,它也不能帮助你实现学习正则表达式的目标,而我会假设这个特定的 HTML 解析项目只是其中一部分。

实现起来非常简单:

from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup(html_to_parse)
for tag in soup.findAll('a', href=True):
    print(tag['href'])

无论如何,一旦你安装了BeautifulSoup。


4
学习正则表达式的一部分是学会何时不使用它们,这是一个你不应该使用它们的情况。 - Chas. Owens
2
有些页面格式非常糟糕,即使使用BeautifulSoup也无法找到其中的链接。那么你就必须采取其他方法。 - Petter H
正则表达式的小改进:re.findall(r'href\s?=\s?[\'"]?([^\'" >]+)', show_notes),允许等号前后有空格。 - Leon Overweel
你确定是“match.group(0)”而不是“match.group(1)”吗? - pah8J
if match:写成if match is not None:是否更有意义,更正确呢? - blizz
@blizz其实并不重要;re.search会返回一个匹配对象或None,而且没有其他可能的假值返回(即我们不需要在这里区分None和False)。因此,if match:更加简洁明了。 - David

13

不要使用正则表达式,使用BeautifulSoup。或者是非常笨拙地将其分离到像w3m/lynx这样的工具中,并拉回w3m/lynx渲染的内容。第一个可能更优雅,第二个在我以前编写的一些未经优化的代码上运行得更快。


13

这应该可以工作,虽然可能有更优雅的方法。

import re
url='<a href="http://www.ptop.se" target="_blank">http://www.ptop.se</a>'
r = re.compile('(?<=href=").*?(?=")')
r.findall(url)

2
(?<=href=["']).*?(?=["']) 可以处理单引号的 href。 - Neil

12

约翰·格鲁伯(John Gruber)编写了Markdown,这是由正则表达式构成的,并且在Stack Overflow上使用。他尝试编写了一个用于识别文本中URL的正则表达式:

http://daringfireball.net/2009/11/liberal_regex_for_matching_urls

如果你只想获取URL(即你不需要解析HTML),这可能比HTML解析器更轻量级。


3

3

这个正则表达式可以帮助你,你需要通过 \1 或者你语言中的其他方法来获得第一组。

href="([^"]*)

示例:

<a href="http://www.amghezi.com">amgheziName</a>

结果:

http://www.amghezi.com

2

这些正则表达式在regexlib上有大量提供。


1

是的,在regexlib上有很多这样的东西。这只证明了正则表达式不应该用来做那个。使用SGMLParser或BeautifulSoup或编写解析器-但不要使用正则表达式。那些看起来有效的RE非常复杂,仍然不能涵盖所有情况。


1
这种方法使用可选匹配(在href=之后打印)非常有效,并仅获取链接。 在http://pythex.org/上进行了测试。
(?:href=['"])([:/.A-z?<_&\s=>0-9;-]+)

输出:

匹配 1. /wiki/Main_Page

匹配 2. /wiki/Portal:Contents

匹配 3. /wiki/Portal:Featured_content

匹配 4. /wiki/Portal:Current_events

匹配 5. /wiki/Special:Random

匹配 6. //donate.wikimedia.org/wiki/Special:FundraiserRedirector?utm_source=donate&utm_medium=sidebar&utm_campaign=C13_en.wikipedia.org&uselang=en


在Python程序中输入此正则表达式(而非通过您提到的网站),由于使用了文本引号'",将会出现错误。为修复此问题,应在 '" 前添加一个斜杠 \,使正则表达式变为:regex='(?:href=[\'"])([:/.A-z?<_&\s=>0-9;-]+)' - Mohammad ElNesr

-1

你可以使用这个。

<a[^>]+href=["'](.*?)["']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接