但它允许您添加和查询特定成员。 幸运的是,我们不需要知道我们看到的所有 URL,只需回答这个问题:我们看到的是 _这个_ url 还是 _那个_ url。 您不能要求布隆过滤器列出集合的所有成员,但它允许您添加和查询特定成员。 幸运的是,我们不需要知道我们看到的所有 URL,只需回答这个问题:我们看到的是 _这个_ url 还是 _那个_ url。布隆过滤器有几个缺点:1) 它们不支持删除,2) 它们的误报率确实很小。可以通过分配更多内存空间来控制误报率,我们将我们的误报率限制为 1/100,000。 在实践中,它通常低于该限制,但这是我们可以接受的最高比率。为了解决无法从集合中删除项目的问题,我们必须求助于其他技巧。 我们实际上维护了多个布隆过滤器;一个用于当前月份,另一个用于上个月,依此类推。
我们只将我们看到的 URL 添加到当前月份
但在过滤 URL 时,我们会检查 捷克手机号码 过去 _k_ 个月的每个过滤器。 为了允许这些操作分布在多个工作器上,我们使用一个名为Redis 的内存(但由磁盘支持)数据库 和我们自己的 Python 绑定,用于 Redis 中的布隆过滤器pyreBloom。 这使我们能够每秒过滤数万个 URL,从而保持同步。
爬行 我们已经对基于
Python 的爬虫进行了多次迭代,并在过 Samsonite 的 Meghan O’Keefe:提高效率的电子商务策略 程中吸取了许多教训。 这个主题足以写一篇文章,因此如果您感兴趣,请关注开发博客 以获取有关该主题的文章。 其要点是,我们需要一种高效地并行从多个来源获取 URL 的方法。 在实践中,对于 Fresh Web Explorer 来说,任何时候都有数百或数千个主机,但在高峰期则达到数万个。
您的第一直觉可能是使用线程
(这不是一个坏直觉),但它会带 白俄罗斯商业名录 来很多效率低下的问题,而且会牺牲概念的简单性。 有一些广为人知的异步 I/O 机制。根据您所处的圈子,您可能遇到过其中一些机制。Node.js、Twisted、Tornado、libev、libevent 等。 从根本上讲,它们都使用两个主要库:kqueue 和 epoll(取决于您的系统)。
问题是这些库公开了一个回调接口
这使得保持代码简洁明了变得非常困难。 回调是您编写的一个函数,当库完成处理后,将其交给库运行。它的意思是,“获取此页面,完成后,使用结果运行此函数。 ”虽然这并不总是会导致代码复杂化,但它很容易导致所谓的“回调地狱”。 线程鲜为人知的“表亲”——协程和gevent为我们解了围。