在Python中比较大字符串的好方法?

时间:2013-03-31 18:12:48

标签: python string compare beautifulsoup match

我构建/扩展了一个Python网页抓取工具,它通过一个网站并构建一个字典来存储它找到的内容(这里是我使用的模板,如果有人感兴趣,那就非常好:http://berrytutorials.blogspot.ca/2010/03/simple-web-crawler-in-python-using.html)。字典比这更多,但出于这个问题的目的,单个项目基本上是{page_url : html}形式,其中html是字符串形式的页面的整个html。

爬虫程序是为了不对同一页面进行两次索引而构建的,但是模板作者指出的一个潜在问题很容易出现,因为url参数不同,爬虫会将相同的页面识别为不同。例如,www.example.com / path?param = 1和www.example.com/path?param=2都会被添加到字典中,因为网址在技术上是不同的,即使每个页面的内容可能相同,或几乎相同。我能想到解决这个问题的唯一方法是在完成刮擦后比较存储在字典中的大量html字符串,看看是否有任何匹配 - 基本上只是

    if html_str_1 == html_str_2:
        # eliminate one of them
每个可能的一对

。但显然这将耗费资源和时间。

有人知道更好的方法吗?我也希望能够检测到几乎相同的html,这些html可能只有少数几个微不足道的字符。我是Python的新手,所以我并不熟悉各种各样的库。也许BeautifulSoup可以做这样的事情吗?

(注意:我知道我给出的示例我可以在分析之前解析网址中的任何参数,但这只是重复html的一个可能原因,我想要涵盖所有内容。此外,可能会产生不同的参数在某些情况下,在完全不同的页面中。)

4 个答案:

答案 0 :(得分:2)

创建HTML的hash并对其进行比较。我建议hashlib.sha512()

In [1]: from hashlib import sha512

In [2]: html = '<p>This is a test</p>'

In [3]: sha512(html).digest()
Out[3]: '\xb4\xda\xc2\xcb\x16\xd3\\\xa1F\x8a\\\xe5-z\xc6\xd1\xf95\x0f\x13\xf6k\xb4\xfd\xb9I\xde\xf0\x8dQ\xff\xdb\x9d\xa2\x0f\x1b\x8al\xfe\xac\xce\xe4n*\xd3\xd8M\xf3E\x05\xc6\xc9\xeejV8\xf8\x9a:\x86|q\x1f\x1c'

您应该更改字典以存储哈希值;

{page_url : (hash, html)}

编辑:散列非常快。我创建了一个10MB的随机数据文件:

dd if=/dev/random of=random.dat bs=1M count=10

阅读并整理它:

In [6]: with open('random.dat') as infile:
    data = infile.read()
   ...:     

In [7]: %timeit sha512(data).digest()
10 loops, best of 3: 61.5 ms per loop

所以你可以在大约60毫秒内散列10MB。

MD5哈希的速度是原来的两倍;

In [4]: %timeit md5(data).digest()
10 loops, best of 3: 24.1 ms per loop

但碰撞的可能性(两个不同的文本产生相同的哈希值)有点大。

答案 1 :(得分:2)

使用类似md5的内容来散列HTML,然后使用两个词典:一个映射URL到content-hash,另一个映射内容哈希到实际内容。例如,而不是:

dict1[ url ] = html

使用:

import md5

h = md5.new()
h.update(html)
k = h.hexdigest()
dict1[ url ] = k
dict2[ k ] = html

这样,相同的页面只会存储一次。

答案 2 :(得分:2)

哈希是要走的路。我会选择MD5,因为它很快 - 它对于加密目的来说是一个缺点,但使用昂贵的哈希(如SHA512)进行索引只会浪费你的周期。

由于网页通常包含基于他们自己的请求选项的链接(如您的示例所示),并且可能是显示提取时间的时间戳,因此您需要在哈希之前清理/规范化已提取的页面他们。删除您认为可能在相同页面之间变化的任何内容,散列结果,并将其用作字典键。这样你可以检查一个新页面是否已知名称为O(1)时间的哈希值 - 由python的字典管理提供。

答案 3 :(得分:1)

  

有人知道更好的方法吗?

理想的方式是首先

  • 比较内容的大小
  • 后跟随机字符子集
  • 后跟整个内容
  

我也希望能够检测到几乎相同的html   不同之处仅在于一些微不足道的角色。

Python的库difflib支持这一点,但资源密集。