Python中的多步骤并发HTTP请求

时间:2012-07-16 00:56:06

标签: python asynchronous concurrency web-scraping

我需要在Python中进行一些三步网页抓取。我最初有几个基页,我需要从这些页面中获取一些选择链接并检索它们指向的页面,然后再重复一次。诀窍是我想异步执行所有操作,以便尽快启动每个请求,并且不会在单个请求中阻止整个应用程序。我该怎么做?

到目前为止,我一直在用eventlet进行一步一步的抓取,如下所示:

urls = ['http://example.com', '...']
def scrape_page(url):
    """Gets the data from the web page."""
    body = eventlet.green.urllib2.urlopen(url).read()
    # Do something with body
    return data

pool = eventlet.GreenPool()
for data in pool.imap(screen_scrape, urls):
    # Handle the data...

但是,如果我扩展此技术并包含嵌套的GreenPool.imap循环,它将阻塞,直到该组中的所有请求都完成为止,这意味着应用程序无法根据需要启动更多请求。

我知道我可以使用Twisted或其他异步服务器执行此操作,但我不需要这么大的库,我宁愿使用轻量级的东西。不过,我愿意接受建议。

1 个答案:

答案 0 :(得分:3)

这是一个想法...但请原谅我,因为我不知道eventlet。我只能提供一个粗略的概念。

考虑你的“第1步”汇集生产者。创建一个queue并让您的第1步工作人员将他们找到的任何新网址放入队列中。

创建另一个工作池。让这些工作人员从队列中提取URL并处理它们。如果在他们的过程中他们发现了另一个URL,请将其放入队列中。他们将继续为后续工作提供食物。

从技术上讲,这种方法可以轻松递归超过1,2,3+步骤。只要他们找到新的网址并将其放入队列,工作就会继续进行。

更好的是,从队列中的原始URL开始,然后创建一个将新URL添加到同一队列的单个池。只需要一个游泳池。

发布便笺

有趣的是,在我发布这个答案后,我去找了一个等同于''队列'的队列,我立即找到了一个显示我刚刚描述的内容的例子:

http://eventlet.net/doc/examples.html#producer-consumer-web-crawler

在该示例中,有producerfetch方法。生产者开始从队列中提取URL并将线程生成到fetchfetch然后将任何新的网址放回队列中,并且他们继续互相喂食。