使用Python从HTML的href属性中提取URL的正则表达式

85
抱歉,我只能使用英语回答问题。
string = "<p>Hello World</p><a href="http://example.com">More Examples</a><a href="http://2.example">Even More Examples</a>"

如何使用Python从锚标签的href中提取URL?类似于以下代码:

>>> url = getURLs(string)
>>> url
['http://example.com', 'http://2.example']

3
不要尝试使用正则表达式解析HTML。寻找一个HTML解析器来为您提取“href”值。 - Anders Lindahl
1
@法官约翰·迪德:最好偷懒一点 - pillmuncher
2
请参见:https://dev59.com/WWkw5IYBdhLWcg3wn7-O#31952097 - Paolo Rovelli
2个回答

182
import re

url = '<p>Hello World</p><a href="http://example.com">More Examples</a><a href="http://2.example">Even More Examples</a>'

urls = re.findall('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url)

>>> print urls
['http://example.com', 'http://2.example']

3
在任何正常的网页爬取中,如果href链接的文本部分也是一个链接而不是描述性文本,这只会导致重复。 - Ryan
4
修改这个正则表达式时,请注意[$-_@.&+]中的 '-' 是一个范围运算符,而不是一个字符。这意味着某些字符(例如逗号',')会被重复表示。 - John Lehmann
18
这个正则表达式不考虑 URL 片段(即以 # 结尾的部分)。 - Dr. Jan-Philip Gehrcke
11
如何使用这个方法来捕捉没有 http 的 URL?比如 www.google.comgoogle.com - Matthew Moisen
显示剩余7条评论

68

最佳答案是...

不要使用正则表达式

被接受的答案中的表达式会忽略许多情况。其中,URL中可能包含Unicode字符。你需要的正则表达式在这里,当你查看它后,你可能会得出结论,你实际上并不需要它。最正确的版本长度为一万个字符

诚然,如果你从一些普通的、无结构的文本开始,并且其中有很多URL,那么你可能需要那个一万个字符长的正则表达式。但如果你的输入有结构,请利用这个结构。你声明的目标是“提取锚标签href内的URL”。你为什么要使用一万个字符长的正则表达式,而不是更简单的方法呢?

解析HTML

对于许多任务,使用Beautiful Soup将会更快、更容易使用:

>>> from bs4 import BeautifulSoup as Soup
>>> html = Soup(s, 'html.parser')           # Soup(s, 'lxml') if lxml is installed
>>> [a['href'] for a in html.find_all('a')]
['http://example.com', 'http://2.example']

如果您不想使用外部工具,您也可以直接使用Python内置的HTML解析库。这是一个非常简单的HTMLParser子类,可以完全满足您的需求:

from html.parser import HTMLParser

class MyParser(HTMLParser):
    def __init__(self, output_list=None):
        HTMLParser.__init__(self)
        if output_list is None:
            self.output_list = []
        else:
            self.output_list = output_list
    def handle_starttag(self, tag, attrs):
        if tag == 'a':
            self.output_list.append(dict(attrs).get('href'))

测试:

>>> p = MyParser()
>>> p.feed(s)
>>> p.output_list
['http://example.com', 'http://2.example']

你甚至可以创建一个新的方法,该方法接受一个字符串,调用feed方法,并返回output_list。这是从HTML中提取信息比正则表达式更加强大和可扩展的方式。


所有的__init__self是什么意思? - voices
4
如果你需要按照最初的问题解析href或src,那么“Beautiful is great”就是可以被接受的答案,但请注意这并不能帮助你在字符串中找到URL。 - vinyll
1
这并没有回答问题。问题是关于URL的格式,而不是如何解析HTML。 - Al Sweigart
2
@AlSweigart,我认为可以说该问题的主体是关于解析HTML。 - senderle
不,它们不在<a>标签中。我的语料库是Reddit上帖子的聚合,大多数情况下URL都被缩短了。一个例子是“https://discord.gg/CVaoq4x”。 - pedram bashiri
显示剩余3条评论

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