在Python中快速解析页面链接

1 投票
2 回答
837 浏览
提问于 2025-04-16 18:51

我需要处理很多网页(比如1000个),并把里面的链接换成tinyurl的链接。

现在我用正则表达式来做这件事。

href_link_re = re.compile(r"<a[^>]+?href\s*=\s*(\"|')(.*?)\1[^>]*>", re.S)

但是速度不够快。

到目前为止,我在考虑:

  1. 状态机(这个能不能成功取决于我写代码的聪明程度)
  2. 使用HTML解析器

你能推荐一些更快的方法吗?

编辑:你可能会认为HTML解析器会比正则表达式快,但在我的测试中并不是这样:

from BeautifulSoup import BeautifulSoup, SoupStrainer

import re
import time

__author__ = 'misha'

regex = re.compile(r"<a[^>]+?href\s*=\s*(\"|')(.*?)\1[^>]*>", re.S)

def test(text, fn, desc):

    start = time.time()
    total  = 0
    links = [];
    for i in range(0, 10):
        links = fn(text)
        total += len(links)
    end = time.time()
    print(desc % (end-start, total))
   # print(links)

def parseRegex(text):
    links  = set([])
    for link in regex.findall(text):
        links.add(link[1])
    return links

def parseSoup(text):
    links = set([])
    for link in BeautifulSoup(text, parseOnlyThese=SoupStrainer('a')):
        if link.has_key('href'):
            links.add(link['href'])

    return links



if __name__ == '__main__':
    f = open('/Users/misha/test')
    text = ''.join(f.readlines())
    f.close()

    test(text, parseRegex, "regex time taken: %s found links: %s" )
    test(text, parseSoup, "soup time taken: %s found links: %s" )

输出:

regex time taken: 0.00451803207397 found links: 2450
soup time taken: 0.791836977005 found links: 2450

(测试是维基百科首页的内容)

我一定是用错了soup。我哪里做错了?

2 个回答

1

用正则表达式来解析数据其实是个很糟糕的主意,因为它的速度慢,而且在某些情况下会变得非常复杂,处理起来很麻烦。相反,你可以使用专门处理xhtml的解析器。最好的选择是LXML。或者,你也可以自己写一个解析器,专门为这个目的设计,可以使用LL或LR解析器。例如:ANTLRYAPPSYACCPYBISON等等。

2

LXML 可能是你完成这个任务的最佳选择。你可以看看这个链接:Beautiful Soup 和 LXML 的性能比较。在 LXML 中解析链接非常简单,而且速度很快。

root = lxml.html.fromstring(s)
anchors = root.cssselect("a")
links = [a.get("href") for a in anchors]

撰写回答