Python 在爬行时存储URL

Python 在爬行时存储URL,python,database,url,storage,web-crawler,Python,Database,Url,Storage,Web Crawler,我用Python创建了一个小网络蜘蛛,用来收集URL。我对内容不感兴趣。现在我将所有访问的URL保存在内存中的一个集合中,因为我不希望我的蜘蛛访问URL两次。当然,这是一个非常有限的方式来实现这一点 那么,跟踪我访问过的URL的最佳方法是什么 我应该使用数据库吗 哪一个?MySQL、SQLite、PostgreSQL 我应该如何保存URL?作为主键,在访问每个URL之前尝试插入它 或者我应该把它们写入一个文件 一个文件 多个文件?我应该如何设计文件结构 我肯定有很多关于这个或类似主题的书

我用Python创建了一个小网络蜘蛛,用来收集URL。我对内容不感兴趣。现在我将所有访问的URL保存在内存中的一个集合中,因为我不希望我的蜘蛛访问URL两次。当然,这是一个非常有限的方式来实现这一点

那么,跟踪我访问过的URL的最佳方法是什么

我应该使用数据库吗

  • 哪一个?MySQL、SQLite、PostgreSQL
  • 我应该如何保存URL?作为主键,在访问每个URL之前尝试插入它
或者我应该把它们写入一个文件

  • 一个文件
  • 多个文件?我应该如何设计文件结构

我肯定有很多关于这个或类似主题的书籍和论文。你能给我一些建议我应该读什么吗?

这些对我来说似乎是重要的方面:

  • 您不能将URL保存在内存中,因为RAM会变得太高
  • 您需要快速查找至少0(logn)
  • 你需要快速插入
  • 有很多方法可以做到这一点,这取决于数据库的大小。我认为SQL数据库可以为您的问题提供一个很好的模型

    您可能只需要一个SQLite数据库。通常,字符串查找存在性检查是一项缓慢的操作。为了加快速度,您可以创建URL的CRC哈希,并将CRC和URL存储在数据库中。在CRC字段上有一个索引

    • 插入时:插入URL和哈希
    • 当您想要执行现有查找时:获取潜在新URL的CRC,并检查它是否已经在您的数据库中
    当然,URL哈希有可能发生冲突,但是如果100%的跨度对您来说并不重要,那么当发生冲突时,您可以承受数据库中没有URL的打击


    您还可以通过多种方式减少碰撞。例如,您可以增加CRC的大小(CRC8而不是CRC4),并使用大小更大的哈希算法。或者使用CRC和URL长度

    您只是在存储URL吗?你应该看看mongoDB。这是一个非常容易实现的NoSQL数据库

    它也有python绑定:


    由于您可能会在类似的时间看到类似的URL(例如,在浏览网站时,您会看到许多指向网站主页的链接),因此我建议您将URL保存在字典中,直到您的内存变得有限(只需硬编码一个合理的数字,如10M URL或类似)然后,当字典变得太大时,将其刷新到a


    这样,您的大多数URL检查都将在内存中(这很快),而不在内存中的URL检查仍然只需要从磁盘读取1-2次,以验证您是否访问过它们。

    这取决于您将要进行的爬网的规模,以及您正在进行爬网的机器类型。假设一个典型的URL是一个大约60字节的字符串,那么内存中的一组URL将占用略多于100字节的空间(由于速度原因,Python中的集合和dict永远不允许超过60%的空间)。如果您有一台64位机器(和Python发行版),有大约16GB的RAM可用,那么您肯定可以将超过10GB的内存用于所讨论的关键集,这样您就可以轻松地抓取大约1亿个URL;但在另一个极端,如果你有一台32位的机器,有3GB的RAM,你显然不能在关键的一组上投入超过1GB的内存,将你的URL限制在1000万个左右。Sqlite可以提供大约相同的大小范围,其中32位机器无法做到,但慷慨捐赠的64位机器可以做到——比如说1亿或2亿个URL

    除此之外,我推荐PostgreSQL,它还有一个优点,就是可以在不同的机器上运行(在快速局域网上),基本上没有问题,让您的主机专门用于爬行。我想MySQL&c也可以,但我喜欢PostgreSQL标准的遵从性和健壮性;-)。这将允许,比如说,几十亿个URL没有问题(当然,只是一个快速磁盘,或者更好的RAID安排,以及尽可能多的RAM来加速事情)

    如果偶尔出现误报,可以阻止您对新URL进行爬网,那么尝试使用固定长度哈希代替可能相当长的URL来节省内存/存储是可以的。这样的“冲突”根本不可能发生:即使您只使用8个字节作为散列,当您查看数十亿个URL时,也只会有发生冲突的重大风险(对于这个众所周知的问题,“平方根启发式”)

    使用8字节的字符串来表示URL,内存集体系结构应该可以轻松地在一台资源丰富的机器上支持10亿个或更多的URL,如上所述


    那么,您大概需要爬行多少个URL,以及可以节省多少RAM?-)

    我已经编写了很多爬行器。对我来说,比内存不足更大的问题是,如果代码或机器崩溃,或者您决定需要调整代码,那么可能会丢失您已经插入的所有URL。如果内存耗尽,现在大多数机器和操作系统都会翻页,所以速度会减慢,但仍能正常工作。由于URL不再可用,必须重建一组在运行时数小时内收集的URL,这可能会对生产率造成真正的打击

    将您不想丢失的信息保存在RAM中是不好的。显然,在这一点上,数据库是最好的选择,因为您需要快速随机访问来查看是否已经找到URL。当然,内存中的查找速度更快,但在确定要在内存中保留哪些URL的权衡会增加开销。我没有尝试编写代码来确定需要/不需要哪些URL,而是将其保存在数据库中,并集中精力使代码干净、可维护,使SQL查询和模式合理。将URL字段设置为唯一索引,DBM将