下载多个文件并行的库或工具
我在找一个Python库或者命令行工具,可以同时下载多个文件。现在我下载文件是一个接一个的,这样速度太慢了。我知道在Python里可以写个简单的多线程程序,但我总是会遇到一些麻烦的问题,尤其是在使用线程的时候。我的需求是从网站上获取大量的XML数据。
我对这个解决方案的要求是:
- 要能中断。按下Ctrl+C时,所有下载应该立刻停止。
- 即使主程序崩溃或者出现异常,也不应该留下需要手动结束的进程。
- 要能在Linux和Windows上都能运行。
- 要能重试下载,能应对网络错误,并且要有合理的超时设置。
- 要聪明一点,不要对同一个服务器发起100多个同时下载,而是要以合理的方式排队下载。
- 要能处理重要的HTTP状态码,比如301、302和304。这意味着每个文件都要根据上次的Last-Modified值来判断,只有在文件有变化时才下载。
- 最好有个进度条,或者很容易写一个进度条来监控所有文件的下载进度。
- 最好能利用HTTP的keep-alive功能,以提高传输速度。
请不要建议我如何实现这些要求。我想要的是一个现成的、经过验证的解决方案。
我想再说一下我为什么需要这个工具……我有大约300个不同的数据源,都是XML格式的文件,来自50个数据提供者。每个文件的大小在100KB到5MB之间。我需要频繁地获取这些数据(大概每几分钟一次),以确定是否有新的数据需要处理。所以下载工具需要使用HTTP缓存,以减少需要下载的数据量。显然,它还会使用gzip压缩。
然后最大的问题是如何尽可能高效地使用带宽,而不触犯任何限制。例如,一个数据提供者可能会认为你同时打开20个连接在滥用他们的数据源。相反,使用一两个连接来重复下载多个文件可能更好。或者你的网络连接可能会有一些奇怪的限制……我的ISP限制了你能进行的DNS查询次数,所以有个DNS缓存会很不错。
10 个回答
我觉得没有一个完全符合你需求的库,所以你可能需要自己写一个。我建议你看看gevent这个工具,它可以帮助你完成这个任务。他们甚至提供了一个示例脚本,叫做concurrent_download.py。然后,你可以使用urllib2来处理其他大部分需求,比如处理HTTP状态码,还有显示下载进度。
有很多选择,但找到一个完全符合你需求的可能会很难。
在你的情况下,可以试试这个方法:
- 创建一个队列。
- 把要下载的链接放进这个队列里(或者放一些“配置对象”,这些对象里包含链接和其他信息,比如用户名、目标文件等)。
- 创建一组线程。
- 每个线程应该从队列里取一个链接(或者一个配置对象)来处理。
再用一个线程来收集结果(也就是另一个队列)。当结果对象的数量等于第一个队列里放入的数量时,你就完成了。
确保所有的交流都是通过队列或“配置对象”进行的。尽量避免直接访问多个线程共享的数据结构。这样可以帮你解决99%的问题。
你可以试试pycurl,虽然一开始用起来可能不太容易,但看了例子之后就会发现其实不难。我用它在一台配置很低的Linux电脑上同时抓取了成千上万的网页。
- 你不需要处理线程,所以它能优雅地结束,不会留下任何进程。
- 它提供了超时设置和HTTP状态处理的选项。
- 它在Linux和Windows上都能使用。
唯一的问题是,它提供的只是一个基本的框架(其实就是在优秀的curl库上加了一层Python的封装)。你需要写几行代码才能实现你想要的功能。