我正在构建一个必须抓取数百个网站的网络抓取工具。我的抓取工具会保留已经抓取的网址列表。每当抓取工具要抓取新网页时,它首先会搜索已经抓取的网址列表,如果已经列出,则抓取工具会跳到下一个网址,依此类推。抓取网址后,会将其添加到列表中。
目前,我正在使用二进制搜索来搜索网址列表,但问题是,一旦列表变大,搜索就变得非常慢。所以,我的问题是我可以使用什么算法来搜索网址列表(列表大小每天增长到大约20k到100k)。
Crawler目前用Python编码。但我打算将它移植到C ++或其他更好的语言。
答案 0 :(得分:3)
您必须在某个时候决定您希望抓取列表的大小。高达数千万个项目,您可以将URL存储在哈希映射或字典中,这样就可以进行O(1)查找。
在任何情况下,平均网址长度大约为80个字符(这是我五年前运行分布式抓取工具时的体验),您只需要获得每千兆字节大约1000万个网址。因此,您必须开始考虑压缩数据或在一段时间后重新爬行。如果您每天只添加100,000个网址,则需要100天才能抓取1000万个网址。这可能是足够的时间来重新抓取。
如果这些是你的限制,那么我会建议一个由URL键入的简单字典或哈希映射。该值应包含上次爬网日期以及您认为与之相关的任何其他信息。将该数据结构限制为1000万个URL。它可能会占用接近2 GB的空间,这会占用字典开销等等。
你必须定期修剪它。我的建议是拥有一个每天运行一次的计时器,并清除任何超过X天前爬网的URL。在这种情况下,您可能会将X设置为100.这样每天就会为您提供100天的100,000个网址。
如果您开始讨论每天处理数百万个网址的高容量抓取工具,那么您将涉及更多涉及的数据结构和创造性方法来管理复杂性。但是从问题的基调来看,这不是你感兴趣的。
答案 1 :(得分:-1)
我认为在将它们放入二进制搜索列表之前对您的值进行哈希处理 - 这将消除字符串比较的可能瓶颈,交换到int相等检查。它还保留了O(log2(n))二进制搜索时间 - 如果在运行之间使用python的内置hash()
,则可能无法获得一致的结果,但是它是特定于实现的。在一次运行中,它将是一致的。总是可以选择实现自己的哈希,这些哈希在会话之间也可以保持一致。