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

79 python regex url

可能重复:
检查字符串是否为有效URL的最佳正则表达式是什么?

考虑如下字符串:

string = "<p>Hello World</p><a href="http://example.com">More Examples</a><a href="http://example2.com">Even More Examples</a>"
Run Code Online (Sandbox Code Playgroud)

我怎么能用Python在锚标记的href中提取网址?就像是:

>>> url = getURLs(string)
>>> url
['http://example.com', 'http://example2.com']
Run Code Online (Sandbox Code Playgroud)

谢谢!

Joh*_*nGa 174

import re

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

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

>>> print urls
['http://example.com', 'http://example2.com']
Run Code Online (Sandbox Code Playgroud)

  • 此正则表达式不考虑URL片段(#suffix). (14认同)
  • 如何在不使用`http`的情况下捕获URL?比如`www.google.com`或`google.com` (11认同)
  • 对于修改此正则表达式的人,请注意[$ -_ @.&+]中的" - "表示作为范围运算符而不是字符.这意味着某些椅子(例如',')不止一次出现. (4认同)
  • 在任何类型的正常抓取中,href的文本部分也是链接而不是描述性文本,这只是重复. (2认同)

sen*_*rle 54

最好的答案是......

不要使用正则表达式

接受的答案中的表达错过了许多案例.除其他外,URL中可以包含unicode字符.你想要的正则表达式就在这里,看了之后,你可能会得出结论,毕竟你并不是真的想要它.最正确的版本是一万个字符长.

不可否认,如果您从简单的非结构化文本开始,其中包含一堆URL,那么您可能需要一万个字符长的正则表达式.但如果您的输入是结构化的,请使用该结构.您声明的目标是"在锚标记的href中提取网址".当你可以做一些更简单的事情时,为什么要使用一个长达一万字符的正则表达式呢?

改为解析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://example2.com']
Run Code Online (Sandbox Code Playgroud)

如果您不想使用外部工具,也可以直接使用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'))
Run Code Online (Sandbox Code Playgroud)

测试:

>>> p = MyParser()
>>> p.feed(s)
>>> p.output_list
['http://example.com', 'http://example2.com']
Run Code Online (Sandbox Code Playgroud)

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

  • 美丽是伟大的你需要在初始问题中解析href或src,并且应该是接受的答案,但要注意它不会有助于在字符串中查找URL. (4认同)
  • @AlSweigart,我认为可以合理地说问题的主体是关于解析 HTML 的。 (2认同)