我正在从互联网上下载图片,事实证明,我需要下载大量图片。我正在使用以下代码片段的版本(实际上循环通过我打算下载和下载图片的链接:
import urllib
urllib.urlretrieve(link, filename)
我每15分钟下载大约1000张图片,根据我需要下载的图片数量非常慢。
为了提高效率,我每隔5秒设置一次超时(仍有很多下载时间更长):
import socket
socket.setdefaulttimeout(5)
除了在计算机集群上运行作业以并行化下载之外,有没有办法让图片下载更快/更有效?
答案 0 :(得分:2)
我的代码非常天真,因为我没有利用多线程。显然需要响应url请求,但在代理服务器响应时计算机无法进行进一步请求。
进行以下调整,您可以将效率提高10倍 - 还有其他方法可以提高效率,包括scrapy等。
要添加多线程,请使用多处理包执行以下操作:
1)将url检索封装在函数中:
import import urllib.request
def geturl(link,i):
try:
urllib.request.urlretrieve(link, str(i)+".jpg")
except:
pass
2)然后创建一个包含所有网址的集合以及下载图片所需的名称:
urls = [url1,url2,url3,urln]
names = [i for i in range(0,len(urls))]
3)从多处理包导入Pool类,并使用这样的类创建一个对象(显然,你将在真实程序的代码的第一行包含所有导入):
from multiprocessing.dummy import Pool as ThreadPool
pool = ThreadPool(100)
然后使用pool.starmap()方法并传递函数和函数的参数。
results = pool.starmap(geturl, zip(links, d))
注意:pool.starmap()仅适用于Python 3
答案 1 :(得分:0)
当程序进入I / O等待时,执行暂停,以便内核可以执行与I / O请求相关的低级操作(这称为context switch)
,并且直到I / O操作完成。
上下文切换是一项非常繁重的操作。它要求我们保存程序的状态(丢失我们在CPU级别的任何类型的缓存)并放弃使用CPU。之后,当我们被允许再次运行时,我们必须花时间在主板上重新初始化我们的程序并准备好恢复(当然,所有这些都发生在幕后)。
另一方面,对于concurrency,
,我们通常会运行一个名为“事件循环”的东西来管理在我们的程序中运行的内容以及何时运行。实质上,事件循环只是需要运行的函数列表。列表顶部的函数运行,然后运行下一个等等。
以下显示了一个事件循环的简单示例:
from Queue import Queue
from functools import partial
eventloop = None
class EventLoop(Queue):
def start(self):
while True:
function = self.get()
function()
def do_hello():
global eventloop
print "Hello"
eventloop.put(do_world)
def do_world():
global eventloop
print "world"
eventloop.put(do_hello)
if __name__ == "__main__":
eventloop = EventLoop()
eventloop.put(do_hello)
eventloop.start()
如果以上内容似乎是您可以使用的内容,并且您还想了解gevent,
tornado,
和AsyncIO,
如何帮助解决您的问题,那么请前往您的(大学图书馆,查看High Performance Python by Micha Gorelick and Ian Ozsvald,阅读第181-202页。
注意:上面的代码和文字来自book提到的。