用于并行下载多个文件的库或工具

时间:2011-07-19 16:28:12

标签: python http parallel-processing download feed

我正在寻找一个用于并行下载多个文件的python库或命令行工具。我目前的解决方案是按顺序下载文件,这很慢。我知道你可以很容易地在python中编写一个半成熟的线程解决方案,但是在使用线程时我总是遇到烦人的问题。它用于从网站轮询大量xml提要。

我对解决方案的要求是:

  1. 应该是可以打断的。 Ctrl + C应立即终止所有下载。
  2. 即使主程序崩溃或抛出异常,也不应该使用kill手动杀死剩余的进程。
  3. 它也适用于Linux和Windows。
  4. 它应该重试下载,对网络错误具有弹性并且应该正常超时。
  5. 应该明智的做法是不要同时下载100多个同一台服务器,但要以理智的方式排队。
  6. 它应该处理重要的http状态代码,如301,302和304.这意味着对于每个文件,它应该将Last-Modified值作为输入,并且只有在自上次更改后才下载。
  7. 最好它应该有一个进度条,或者应该很容易为它编写一个进度条来监控所有文件的下载进度。
  8. 最好是利用http keep-alive来最大化传输速度。
  9. 不建议我如何实施上述要求。我正在寻找一个现成的,经过实战考验的解决方案。

    我想我应该描述我想要的东西......我有大约300种不同的数据源作为xml格式的文件,由50个数据提供者提供。每个文件的大小在100kb到5mb之间。我需要经常轮询它们(如每隔几分钟一次)以确定它们是否有我需要处理的新数据。因此,下载程序使用http缓存来最小化要获取的数据量非常重要。它显然也使用gzip压缩。

    然后,最大的问题是如何在不超越任何边界的情况下以尽可能高效的方式使用带宽。例如,如果您打开20个同时连接到其数据源的连接,则一个数据提供商可能会认为它被滥用。相反,最好使用一个或两个重用于多个文件的连接。或者您自己的连接可能会以奇怪的方式受到限制。我的isp限制了您可以执行的dns查找次数,因此某种dns缓存会很好。

10 个答案:

答案 0 :(得分:8)

你可以试试pycurl,虽然界面起初并不容易,但是一旦看了例子,就不难理解了。我用它在微薄的linux盒子上并行获取1000个网页。

  1. 您不必处理线程,因此它会优雅地终止,并且不会留下任何进程
  2. 它提供超时和http状态处理选项。
  3. 适用于Linux和Windows。
  4. 唯一的问题是它提供了一个基本的基础设施(基本上只是一个优秀的curl库上面的python层)。您将不得不写几行来实现您想要的功能。

答案 1 :(得分:7)

有很多选择,但很难找到符合您所有需求的选项。

在您的情况下,请尝试以下方法:

  1. 创建一个队列。
  2. 将URL下载到此队列中(或“配置对象”,其中包含URL和其他数据,如用户名,目标文件等)。
  3. 创建一个线程池
  4. 每个线程都应该尝试从队列中获取URL(或配置对象)并进行处理。
  5. 使用另一个线程来收集结果(即另一个队列)。当结果对象的数量= =第一个队列中的放置次数时,您就完成了。

    确保所有通信都通过队列或“配置对象”进行。避免访问线程之间共享的数据结构。这可以为你节省99%的问题。

答案 2 :(得分:2)

我不认为这样一个完整的库存在,所以你可能需要编写自己的库。我建议看看gevent来完成这项任务。他们甚至提供了concurrent_download.py示例脚本。然后,您可以将urllib2用于大多数其他要求,例如handling HTTP status codesdisplaying download progress

答案 3 :(得分:2)

我建议使用Twisted,虽然它不是现成的解决方案,但提供了主要的构建块,以便以简单的方式获得您列出的每个功能,并且它不使用线程。

如果您有兴趣,请查看以下链接:

根据您的要求:

  1. 支持开箱即用
  2. 支持开箱即用
  3. 支持开箱即用
  4. 支持开箱即用超时,通过延迟完成其他错误处理
  5. 使用cooperators (example 7)
  6. 轻松实现
  7. 支持开箱即用
  8. 不支持,解决方案存在(并且它们并不难实现)
  9. 不支持,可以实施(但会相对较难)

答案 4 :(得分:2)

现在您可能想要使用优秀的Python库 - urllib3requests

答案 5 :(得分:1)

尝试通过简单的python aria2模块使用subprocess。 它提供了列表中的所有要求,除了7,开箱即用,7易于编写。 aria2c有一个很好的xml-rpc或json-rpc接口,可以从你的脚本中与它进行交互。

答案 6 :(得分:0)

除非你是一个糟糕的程序员,否则线程不会“半开玩笑”。解决此问题的最佳方法是生产者/消费者模型。您有一个专用的URL生成器和 N 专用下载线程(如果使用多处理模型,甚至是进程)。

至于你的所有要求,所有这些都可以使用普通的python线程模型完成(是的,甚至可以使用Ctrl + C - 我已经完成了它。)

答案 7 :(得分:0)

urlgrabber是否符合您的要求?

http://urlgrabber.baseurl.org/

如果没有,你可以考虑自愿帮助完成它。联系作者Michael Stenner和Ryan Tomayko。

更新:谷歌搜索“并行wget”产生这些,其中包括:

http://puf.sourceforge.net/

http://www.commandlinefu.com/commands/view/3269/parallel-file-downloading-with-wget

您似乎有多种选择可供选择。

答案 8 :(得分:0)

我使用了标准的库,urllib.urlretrieve是准确的。以这种方式下载播客,通过一个简单的线程池,每个使用自己的检索。我做了大约10个同时连接,更不应该是一个问题。继续中断下载,也许不是。我想可以处理Ctrl-C。在Windows上工作,安装了进度条的处理程序。总共2个代码屏幕,2个用于生成要检索的URL的屏幕。

答案 9 :(得分:0)