并行下载多个文件的库或工具[关闭]
Posted
技术标签:
【中文标题】并行下载多个文件的库或工具[关闭]【英文标题】:Library or tool to download multiple files in parallel [closed] 【发布时间】:2011-10-08 16:49:25 【问题描述】:我正在寻找用于并行下载多个文件的 python 库或命令行工具。我目前的解决方案是按顺序下载文件,这很慢。我知道你可以很容易地用 python 编写一个半途而废的线程解决方案,但是在使用线程时我总是遇到烦人的问题。它用于轮询来自网站的大量 xml 提要。
我对解决方案的要求是:
-
应该是可中断的。 Ctrl+C 应立即终止所有下载。
即使主程序崩溃或抛出异常,也不应该有剩余的进程需要使用 kill 手动杀死。
它应该也可以在 Linux 和 Windows 上运行。
它应该重试下载,能够抵御网络错误并且应该正确超时。
明智的做法是不要在同一台服务器上同时下载 100 多个下载,而是以理智的方式将它们排队。
它应该处理重要的 http 状态代码,如 301、302 和 304。这意味着对于每个文件,它应该将 Last-Modified 值作为输入,并且仅在自上次更改后才下载。
最好有进度条,或者方便写进度条,监控所有文件的下载进度。
最好利用 http keep-alive 来最大化传输速度。
请不要建议我如何着手实施上述要求。我正在寻找一个现成的、经过实战考验的解决方案。
我想我也应该描述一下我想要它的用途...我有大约 300 个不同的数据馈送,这些数据馈送是由 50 个数据提供者提供的 xml 格式文件。每个文件的大小在 100kb 到 5mb 之间。我需要经常轮询它们(如每隔几分钟一次)以确定它们中是否有我需要处理的新数据。因此,下载器使用 http 缓存来最小化要获取的数据量是很重要的。它显然也使用 gzip 压缩。
那么最大的问题是如何以尽可能有效的方式使用带宽,而不会越界。例如,如果您同时打开 20 个与其数据馈送的连接,一位数据提供商可能会认为这是滥用行为。相反,最好使用一个或两个可重复用于多个文件的连接。或者您自己的连接可能会以奇怪的方式受到限制。我的 isp 限制了您可以执行的 dns 查找次数,因此某种 dns 缓存会很好。
【问题讨论】:
这就是线程的用途。 您具体面临什么问题? 如果你想要一个现成的、久经考验的命令行工具......你为什么关心它是否是用 Python 编写的? 【参考方案1】:你可以试试pycurl,虽然一开始界面不太好,但是看了例子就不难理解了。我用它在微不足道的 linux 机器上并行获取 1000 个网页。
-
您不必处理线程,因此它会优雅地终止,并且不会留下任何进程
它提供了超时选项和 http 状态处理选项。
它适用于 linux 和 windows。
唯一的问题是它提供了一个基本的基础设施(基本上只是优秀的 curl 库之上的一个 python 层)。您将不得不编写几行代码来实现您想要的功能。
【讨论】:
【参考方案2】:有很多选择,但很难找到适合您所有需求的选择。
在你的情况下,试试这个方法:
-
创建队列。
将要下载的 URL 放入此队列(或“配置对象”,其中包含 URL 和其他数据,如用户名、目标文件等)。
创建线程池
每个线程都应尝试从队列中获取 URL(或配置对象)并对其进行处理。
使用另一个线程来收集结果(即另一个队列)。当结果对象的数量 == 第一个队列中放入的数量时,您就完成了。
确保所有通信都通过队列或“配置对象”进行。避免访问线程之间共享的数据结构。这应该可以为您解决 99% 的问题。
【讨论】:
请不要建议我如何去实现上述要求。我正在寻找一个现成的、经过实战考验的解决方案。 看来你正在这样做。 GaretJax:如果你看一下编辑历史,上面的答案是在提问者添加这句话之前十分钟做出的。 @Peter O.:你是对的,对此感到抱歉。【参考方案3】:我认为不存在这样一个完整的库,因此您可能必须编写自己的库。我建议查看gevent 来完成这项任务。他们甚至提供了concurrent_download.py 示例脚本。然后您可以将urllib2 用于大多数其他要求,例如handling HTTP status codes 和displaying download progress。
【讨论】:
恐怕gevent在windows上不可用。 gevent 在 Windows 上工作,甚至有 Windows 版本:code.google.com/p/gevent/downloads/list【参考方案4】:我会推荐 Twisted,虽然它不是一个现成的解决方案,但它提供了主要的构建块,可以轻松地获取您列出的每个功能,并且它不使用线程。
如果您有兴趣,请查看以下链接:
http://twistedmatrix.com/documents/current/api/twisted.web.client.html#getPage http://twistedmatrix.com/documents/current/api/twisted.web.client.html#downloadPage根据您的要求:
-
开箱即用支持
开箱即用支持
开箱即用支持
开箱即用支持超时,通过延迟完成其他错误处理
使用cooperators (example 7) 轻松实现
开箱即用支持
不支持,存在解决方案(实施起来并不难)
不支持,可以实现(但会比较难)
【讨论】:
【参考方案5】:如今,您可能想要使用一些出色的 Python 库 - urllib3 和 requests
【讨论】:
【参考方案6】:尝试通过简单的python subprocess 模块使用aria2。 它提供了您列表中的所有要求,除了 7,开箱即用,而且 7 易于编写。 aria2c 有一个不错的 xml-rpc 或 json-rpc 接口,可以通过您的脚本与之交互。
【讨论】:
【参考方案7】:urlgrabber 是否符合您的要求?
http://urlgrabber.baseurl.org/
如果没有,您可以考虑自愿帮助完成它。联系作者 Michael Stenner 和 Ryan Tomayko。
更新:谷歌搜索“parallel wget”会产生以下结果:
http://puf.sourceforge.net/
http://www.commandlinefu.com/commands/view/3269/parallel-file-downloading-with-wget
您似乎有很多选项可供选择。
【讨论】:
谢谢,但这些链接在 4、5、8 尤其是 6 上失败。对我来说,问题不是抛出许多进程来进行下载,而是处理 http 缓存并有一些“全局控制”系统,以便尽可能高效地完成下载。 如果我正在写这篇文章并且所有这些要求都是不可协商的(正如你似乎暗示的那样),我几乎肯定会根据 Twisted 编写自己的下载器。【参考方案8】:我为此使用了标准库,准确地说是urllib.urlretrieve
。以这种方式下载播客,通过一个简单的线程池,每个使用自己的检索。我做了大约10个同时连接,更多应该不是问题。继续中断下载,也许不会。 Ctrl-C 可以处理,我猜。在 Windows 上工作,为进度条安装了一个处理程序。总共 2 个代码屏幕,2 个用于生成要检索的 URL 的屏幕。
【讨论】:
【参考方案9】:这看起来很灵活:
http://keramida.wordpress.com/2010/01/19/parallel-downloads-with-python-and-gnu-wget/
【讨论】:
【参考方案10】:线程不是“半途而废”,除非你是一个糟糕的程序员。解决这个问题的最佳通用方法是生产者/消费者模型。您有一个专用的 URL 生成器,以及 N 个专用的下载线程(如果您使用多处理模型,甚至还有进程)。
至于您的所有要求,所有这些都可以使用普通的 python 线程模型完成(是的,即使是 Ctrl+C ——我已经做到了)。
【讨论】:
由于全局解释器锁,显然多处理对于 Python 中的并发性更好,但假设 GIL 时间足够快,线程可能会很好地处理这种事情,你会遇到什么延迟通常会得到以及每个线程在获得更多数据时将如何阻止 I/O 访问。不过,我不是专家,因此在 Python 中这种情况下多进程可能仍然更好。 是的,因为一切都是 IO 绑定的,所以 GIL 不会产生明显的影响。以上是关于并行下载多个文件的库或工具[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
Android中是不是有波斯(Shamsi或Jalali)日历的库或算法? [关闭]
使用 Delphi 6(C/C++ 也可以)创建视频文件(AVI 等)的库或组件?
Azure Data PlatformETL工具(13)——ADF并行加载多个文件