在Ruby中创建Web爬虫。如何解决性能问题?

时间:2012-09-22 08:32:13

标签: multithreading web-crawler nokogiri mechanize

我正在使用Ruby构建一个Web爬虫,Rails作为前端。我正在使用建立在Nokogiri之上的Mechanize。我已经实现了一个可以抓取网页的解决方案,但我希望能够在一次运行中抓取200k个网站,而且我知道有一个比等待数小时才能完成的更好的方法。我希望能够通过启动并行请求来实现最佳性能,而不会使其过于复杂。我对线程没有任何了解,对它的限制是什么,所以如果有人想指出我可以学习如何做到这一点或者至少告诉我应该做什么,请不要在爬虫运行时保持服务器人质寻找。保持我的意思,我将写入数据库和文件(可能我可以在爬网完成后从数据库导出,而不是直接写入文件)。感谢。

注意:这里有一个类似的问题,但是几年前也许人们现在这样做了很多天,看起来很复杂。

3 个答案:

答案 0 :(得分:5)

使用Typhoeus and Hydra查看。它们可以轻松处理URL 在平行下。

您不需要使用Mechanize,除非您必须从中请求特殊数据 每页。对于普通的爬虫,您可以抓住身体并使用它进行解析 Open :: URI和Nokogiri没有Mechanize的开销或增加的功能。对于 你的目的,用Typhoeus替换Open :: URI并让Hydra处理   线程管理。

请记住,如果您尝试,抓取200k网站会使您的带宽饱和 一次完成所有这些。这将使您的Rails站点不可用,因此您需要 扼杀你的要求。而且,这意味着你必须完成它们 几个(或许多)小时。速度并不像保持网站在线那么重要 这里。我可能会将爬虫放在与Rails服务器不同的机器上 并让数据库将事物联系在一起。

创建包含您要抓取的网站网址的表格或文件。 ID 推荐表格,以便您可以整理表格来编辑/管理网址。 您需要跟踪以下内容:

  • 上次抓取网址的时间。 (日期时间)
  • 是否应抓取特定网址(布尔值或字符1
  • URL(String或var char [1024]应该没问题)。这应该是一个独特的密钥。
  • 当前是否正在抓取该网址(布尔值或字符1)。这在所有记录的运行开始时被清除,然后在蜘蛛加载该页面时设置并离开。
  • 显示何时可以运行该网站的字段。
  • 显示运行该网站的小时数的字段。

最后两个很重要。你不想抓取一个小网站 动力不足并杀死它的联系。这是被禁止的好方法。

创建另一个表,该表是要在特定站点上检查的下一个URL 从您在爬行时遇到的链接收集。你想要上来 使用规范化例程来减少具有会话数据和参数的URL 你可以用来测试唯一性的东西。在这个新表中你会想要的 URL是唯一的,因此您不会进入循环或继续添加相同的页面 具有不同的参数。

您可能需要注意之后检索到的实际登陆网址 重定向而不是“获取”URL,因为重定向和DNS名称可能会有所不同 在网站内部,生成内容的人可能会使用不同的内容 主机名。同样,您可能希望在头部查找元重定向 阻止并跟随他们。做这些事情是一个特别恼人的方面 你想写。

当您遇到新网址时,请检查他们是否正在退出网址 如果你跟着他们,你会离开那个网站。如果是这样,请不要添加它们 你的URL表。

将数据库信息写入文件可能无济于事, 因为要找到正确的文件,您可能需要进行数据库搜索 无论如何。只需在字段中存储您需要的内容并直接请求它。 200K行 在数据库中没什么。

注意网站的“蜘蛛”规则以及它们是否提供了API 在数据上,然后使用它,而不是抓取。

答案 1 :(得分:3)

我不是Ruby专家,但这里有一些基于其他编程语言经验的想法,以及答案:

答:您必须了解Web服务器或运行Ruby应用程序的环境的线程模型。
例如,我正在使用一个名为tomcat的Web服务器,它可以配置它打开的线程数。
当然,这不能超过操作系统上可能的线程数。

B.此外,请记住,由于您需要“爬行”,这意味着您可能需要使用文件(即Linux上的文件描述符),这些资源有限。
例如,在Linux上,您可以使用ulimit配置文件描述符的限制。

C.我会认真地建议你有一个线程池(我确信Ruby有这个框架,here是我在谷歌搜索时出现的东西)。
使用线程池意味着您正在使用线程,但您不是打开/关闭线程,而是拥有一组线程,从共享数据结构中提取作业并执行它们。
例如,你可以做的是,对于每个作业,你将执行以下伪代码:
1.解析网页
2.对于每个链接执行:
2.1。使用URL创建工作。
2.2将作业放在队列中(使线程池线程起作用)

我还会认真考虑使用群集(例如 - 云上的几台机器)并开发可扩展的解决方案。
这意味着您将在群集节点之间拥有某种共享数据结构(可能是数据库或NoSQL DB),并且您的工作线程将提取作业,并将新作业放入此群集(云端)共享数据结构中。
我还建议你阅读map-reduce模式,这可以在这里为你提供帮助,
并且可以将Hadoop与Ruby一起使用(参见here链接)。


再一次,我很抱歉我不是红宝石专家,但我遇到过你正在使用的其他计算机语言的问题。
我希望我给你一些提示和阅读材料。祝你好运!

答案 2 :(得分:0)

检查http://anemone.rubyforge.org/index.html

我认为它可能适合您的需求,如果不是,您应该能够从它的源代码中学到很多东西。