最有效(时间,成本)的方式来刮去500万网页?

我有一个网页的清单,我需要刮,分析,然后将结果数据存储在数据库中。 总数约为500万。

我目前最好的方法是假设部署〜100个EC2实例,为每个实例提供50,000个页面,然后让它们运行,然后一旦这个过程完成,就将数据库合并在一起。 假设是需要花费大约一天的时间来运行(600ms来加载,parsing和保存每个页面)。

有没有人有限的时间内做这么大的页面抓取经验? 我之前(1.5米)已经做了大量的工作,但那是一台机器,花了一个多星期才完成。

我的情况的瓶颈是下载页面,parsing是不超过2毫秒,所以可以简化下载页面的过程是我正在寻找的东西。

假设下载时间(以及带宽使用)是限制因素,我会提出以下build议:

首先,selectm1.large实例。 在I / O性能(包括带宽)的三个“等级”中,m1.large和m1.xlarge实例都提供了“高”I / O性能。 由于你的任务不是CPU绑定的,所以最好的select是最便宜的。

其次,你的实例可以下载的速度远远超过任何网站可以提供页面的速度 – 不要一次下载一个给定的实例的页面,同时运行任务 – 你应该能够同时做至less20页(尽pipe,我想你可以没有困难地做50-100)。 (以您的评论中的论坛为例 – 这是一个dynamic的页面,将花费服务器时间来生成 – 还有其他用户使用该站点的带宽等)。 继续提高并发性,直到达到实例带宽的限制。 (当然,不要同时向同一个站点发出多个请求)。

如果您真的想尽量提高性能,您可以考虑在适合地理位置的区域中启动实例,以最大限度地减less延迟(但这需要将所有url进行地理定位,这可能不实际)。

有一件事要注意的是,实例带宽是可变的,有时你会得到更高的性能,而在其他时候,你会得到更低的性能。 在较小的实例中,性能的变化更为显着,因为物理链接被更多的服务器共享,任何这些都会降低可用带宽。 在EC2networking(同一个可用区域)内的m1.large实例之间,您应该接近理论千兆位吞吐量。

一般来说,使用AWS,使用大型实例(而不是多个小型实例)除非您专门查看诸如故障转移等需要多个实例的内容,否则几乎总是更高效。

我不知道你的设置需要什么,但是当我以前尝试过(在1到200万个链接之间,定期更新)时,我的方法是维护链接的数据库,添加新的链接,刮去和parsing页面。 一个URL将被随机检索并在数据库中标记为正在执行,脚本将下载页面,如果成功,则将url标记为已下载到数据库中,并将内容发送到parsing页面的另一个脚本,新链接被添加到数据库,因为他们被发现。 这里数据库的优点是集中化 – 多个脚本可以同时查询数据库(只要事务是primefaces的),可以确保每个页面只下载一次。

还有一些值得一提的地方 – 对于一次可以运行的点播实例的数量有限制(我相信20) – 如果您计划超出这些限制,则需要请求AWS增加您的帐户限制。 在现货价格低的时候(比如,一个按需的实例来保持所有的事情都是有组织的,以及剩下的现货实例),运行现货实例以及扩大你的数量会更加经济。

如果时间的优先级高于您的成本,则集群计算实例将提供10Gbps的带宽,并且应该产生最大的下载带宽。

回顾一下:尝试几个大型实例(而不是许多小型实例),并在每个实例上运行多个并发下载 – 如果发现自己的带宽有限,则添加更多实例,如果发现自己的CPU /内存被限制,请移至较大的实例。

我们试图做类似的事情,这里是我的5美分:

  1. 获取2-3个便宜的无限量服务器,例如不支付带宽。

  2. 使用python asyncore。 Asyncore是做事的老办法,但是我们发现它比任何其他方法都更快。 不利的一面是DNS查询被阻止,即不是“并行”。 使用asyncore,我们使用单个XEON 4核心,8 GB RAM,设法扫描了1M URL,时间为40分钟。 在服务器上的平均负载less于4(这对4核心来说是非常好的)。

  3. 如果你不喜欢asyncore,试试gevent。 它甚至做DNS不阻塞。 使用gevent,在相同的硬件上下载了大约50分钟的1M。 在服务器上的平均负载是巨大的。

注意我们testing了很多Python库,比如grequests,curl,liburl / liburl2,但是我们没有testingTwisted

  1. 我们testing了PHP + curl +几个进程,它做了大约一个小时的工作,但在服务器上的平均负载是巨大的。