【问题标题】:Best strategy to download many images with Python?使用 Python 下载许多图像的最佳策略?
【发布时间】:2021-06-22 10:25:12
【问题描述】:

我正在尝试从 URL 列表中下载许多图像。很多,我的意思是在 10 000 附近。图像的大小从几百 KB 到 15 MB 不等。 我想知道完成这项任务的最佳策略是什么,尽量减少完成的总时间,并避免冻结。

我用这个函数来保存每张图片:

def save_image(name, base_dir, data):
    with open(base_dir + name, "wb+") as destination:
        for chunk in data:
            destination.write(chunk)

我用这个函数从 URL 中获取文件扩展名:

def get_ext(url):
    """Return the filename extension from url, or ''."""
    """ From : https://stackoverflow.com/questions/28288987/identify-the-file-extension-of-a-url """
    parsed = urlparse(url)
    root, ext = splitext(parsed.path)
    return ext  # or ext[1:] if you don't want the leading '.'

为了得到我刚刚做的图像:

for image in listofimages:
    r = requests.get(image["url"], timeout=5)
    extension = get_ext(image["url"])
    name = str( int(image['ID']) ) + "AA" + extension
    save_image( name, "images/", r )

现在把它们放在一起很慢。因此我的问题。

【问题讨论】:

  • 慢是什么意思?你有证据应该更快吗?缓慢的事情和需要很长时间的事情是有区别的。你说的冻结是什么意思?很有可能对网络带宽、文件系统访问、工作内存、CPU 有限制。管理所有这些将为您的情况提供一些最佳性能。您可能可以相对轻松地使用 multiprocessing 并行化您的代码,这将使用多个 CPU 和网络连接。
  • @PeterWood 考虑到涉及多少 I/O 和网络等待(释放全局解释器锁),我认为多线程会是更好的模型,你当然可以这样做 way 使用比您所提到的解决方案所拥有的 CPU 内核数更大的池大小更好。
  • @PeterWood 冻结,我的意思是我的代码在下载了大约 700 张图像后停止(即不会继续......)。我在控制台中没有收到任何错误,只是不再“继续”了。抱歉没有更准确。

标签: python web-scraping python-requests


【解决方案1】:

一个,正如上面 cmets 中所暗示的,您可能希望并行化工作。多处理和多线程将起作用,但开销相对较高。或者,您可以使用异步方法,例如使用 Gevent 修补您的网络库,或者将 asyncio 与异步感知 HTTP 客户端一起使用,例如,httpx 就可以了。

无论您采用何种方法来并行化 I/O,您都可能会发现 queue 范式使用起来很方便 - 将您的所有 URL 放入一个队列中,并让您的工作人员使用它们。

第二,要处理阻止您的工作人员抓取的无响应 Web 服务器,您可能需要设置套接字超时,检查选择的 HTTP 客户端库是如何做到的。例如,流行的requests 只需使用timeout 参数。

【讨论】:

  • 感谢您的这些建议。我今天会试试看。
  • 您关于超时的评论非常有帮助。在请求示例中设置超时 5 似乎已经解决了到目前为止的冻结问题。
猜你喜欢
  • 1970-01-01
  • 2016-08-01
  • 2011-08-19
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 2016-07-26
  • 2011-02-14
  • 1970-01-01
相关资源
最近更新 更多