存储网络爬虫状态的最佳优化方式是什么?

4
我正在编写一个网络爬虫(使用Python框架scrapy)。最近,我需要实现一个暂停/恢复系统。我实现的解决方案是最简单的一种,基本上在链接被调度时存储链接,并在它们实际被处理时将其标记为“已处理”。因此,在恢复蜘蛛时,我能够获取这些链接(显然比只有URL、深度值、链接所属的域等更多的内容存储),到目前为止一切都正常。目前,我只是使用MySQL表来处理这些存储操作,主要是为了快速原型设计。现在,我想知道如何优化这个过程,因为我认为数据库不应该是唯一可用的选项。通过优化,我的意思是使用非常简单和轻量级的系统,同时仍然能够在短时间内处理大量数据。目前,它应该能够处理几十个域名的爬取,这意味着每秒存储几千个链接...提前感谢您的建议。
2个回答

4
最快的持久化方法通常是将它们附加到日志中--这种完全的顺序访问模式最小化了磁盘寻道,这通常是存储时间成本的最大部分。重新启动时,您会重新阅读日志并重建您在第一次附加到日志时正在构建的内存结构。
您的特定应用程序可以进一步优化,因为它不一定需要100%的可靠性--如果由于突然崩溃而错过写入几个条目,那么好吧,您只需再次爬行它们。因此,您的日志文件可以进行缓冲,并且不需要过于关注fsync。
我想搜索结构也适合内存(如果仅用于几十个站点,则可能只需保留具有所有URL的集合,无需任何花哨的布隆过滤器)。如果没有,您可能必须仅在内存中保留一组最近的条目,并定期将该组转储到磁盘(例如,将所有条目合并为{{link1:Berkeley DB}}文件);但是,我不会详细介绍这些选项,因为似乎您不需要它们。

同时爬取数十个网站,但我想要追踪过去完成的每个爬取任务。 - Sylvain
另外,如果要顺序写入文件,我该如何将链接标记为已下载? - Sylvain
@Sylvain,那么您肯定需要定期将内存中的lookaside set转储到更持久的查找形式,而Berkeley DB可能会或可能不会平稳地扩展到数百万或数十亿...你需要进行基准测试,但我怀疑如果您的规模足够庞大,PostgreSQL(或一些雄心勃勃的非关系型键/值存储,但除了Google自己的Bigtable,我几乎没有经验)确实是您最好的选择。关键是,您不需要一直更新该数据库--使用内存和日志使数据库更新变成“偶尔发生”的事情即可! - Alex Martelli
@Sylvain,你会将“TODO http://a.b.c”或“DONE http://a.b.c”这样的行追加到日志文件中(当然,你也可以使用比“TODO”和“DONE”更短的“动词”;-)。 - Alex Martelli

2

我相当确定不能使用pickle,因为一些对象(来自twisted库)。感谢提供链接,我会尽快查看它。 - Sylvain
最终抽出一些时间来看这个讲座。很有趣。然而,我认为它超出了我的简单需求 :-) - Sylvain

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