0

我需要在 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 或其他异步服务器来做到这一点,但我不需要这么大的库,我宁愿使用轻量级的东西。不过,我愿意接受建议。

4

1 回答 1

3

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

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

创建另一个工人池。让这些工作人员从队列中提取 url 并处理它们。如果在他们的过程中他们发现了另一个 url,将其放入队列中。他们将继续通过后续工作养活自己。

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

更好的是,从队列中的原始 url 开始,然后创建一个将新 url 放入同一个队列的池。只需要一个游泳池。

发布说明

有趣的是,在我发布了这个答案并去寻找 eventlet 'queue' 等效项是什么之后,我立即找到了一个示例,该示例完全显示了我刚才描述的内容:

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

在该示例中,有一个producerandfetch方法。生产者开始从队列中提取 url 并将线程生成到fetch. fetch然后将任何新的 url 放回队列中,它们会继续互相喂食。

于 2012-07-16T05:39:12.170 回答