2

我是 python 的新手,甚至是 twisted 的新手。我正在尝试使用twisted 来下载几十万个文件,但在尝试添加错误反馈时遇到了麻烦。如果下载失败,我想打印错误的 url。为了抛出错误,我故意拼错了我的一个网址。但是,我刚刚挂起的代码并且 python 没有完成(如果我删除 errback 调用,它会很好地完成)。

另外,如何单独处理每个文件?据我了解,当一切完成时,就会调用“完成”。我想在下载每个文件时对其进行 gzip 压缩,以便将其从内存中删除。

这是我所拥有的:

    urls = [
 'http://www.python.org', 
 'http://stackfsdfsdfdsoverflow.com', # misspelled on purpose to generate an error
 'http://www.twistedmatrix.com', 
 'http://www.google.com',
 'http://launchpad.net',
 'http://github.com',
 'http://bitbucket.org',
]

def finish(results):
    for result in results:
        print 'GOT PAGE', len(result), 'bytes'
    reactor.stop() 
def print_badurls(err):
    print err # how do I just print the bad url????????

waiting = [client.getPage(url) for url in urls]
defer.gatherResults(waiting).addCallback(finish).addErrback(print_badurls)

reactor.run() 
4

1 回答 1

2

欢迎来到 Python 和 Twisted!

您粘贴的代码存在一些问题。我会一次过一个。

首先,如果您确实想下载数千个 url,并且urls列表中有数千个项目,那么这一行:

waiting = [client.getPage(url) for url in urls]

会引起问题。您想尝试同时下载列表中的每个页面吗?默认情况下,一般情况下,您在 Twisted 中执行的操作是同时发生的,因此此循环会urls立即开始下载列表中的每个 URL。这很可能是行不通的。您的 DNS 服务器将丢弃一些域查找请求,您的 DNS 客户端将丢弃一些域查找响应。TCP 连接尝试到您返回的任何地址都将竞争任何仍然可用的网络资源,其中一些会超时。其余的连接将全部流淌,在数十个甚至数百个不同的下载之间共享可用带宽。

相反,您可能希望将并发程度限制为一次下载 10 或 20 次。不久前,我在我的博客上写了一种方法。

其次,gatherResults返回 a Deferred,只要任何一个 Deferred传递给它就会触发失败并触发。因此,一旦任何一个client.getPage(url)失败 - 可能是因为我上面提到的问题之一,或者可能是因为域已过期,或者 Web 服务器恰好关闭,或者只是因为不幸的瞬态网络状况,将Deferred返回gatherResults失败。 finish将被跳过,print_badurls并将被调用,并带有描述单个失败getPage调用的错误。

要处理来自单个 HTTP 请求的失败,请将回调和 errbacks 添加到调用Deferred返回的 s 中getPage。添加这些回调和 errbacks 后,您可以使用defer.gatherResults等待所有下载下载结果的处理完成。

第三,您可能需要考虑为此使用更高级别的工具——scrapy是一个网络爬虫框架(基于 Twisted),它为此类应用程序提供了许多很酷且有用的助手。

于 2012-10-07T23:18:39.777 回答