从进程池到线程池:实现高效图片下载

在数字时代,我们每天都能够轻松访问到各种各样的图片,不论是美景、艺术品还是有趣的表情包。然而,有时候我们需要大量的图片数据,例如用于机器学习的训练集或者简单的个人收藏。在这种情况下,如何高效地获取和保存这些图片就成了一个挑战。今天,我将向大家介绍一种使用进程池线程池相结合的方法,以实现高效的图片下载

准备工作

首先,让我们明确一下需要的准备工作。我们将使用Python来完成这个任务,所以确保你已经安装了Python环境。此外,我们还需要以下库:

  • requests:用于发送HTTP请求和获取网页内容。
  • lxml:用于解析HTML文档。
  • multiprocessing:用于创建进程池和进程共享变量。
  • concurrent.futures:用于创建线程池。

确保你已经安装了这些库,如果没有,可以使用pip来安装。

获取图片地址

首先,我们需要获取要下载的图片的地址。在这个例子中,我们将从一个网站上抓取动漫壁纸的图片地址。我们使用了requests库来发送GET请求,然后使用lxml来解析HTML文档,提取出图片的地址。这些地址将被放入一个进程队列中,以便后续的下载。

# 获取图片地址
def get_url(url, que):
    resp = requests.get(url, headers=headers)
    resp.encoding = resp.apparent_encoding
    date = resp.text
    tree = etree.HTML(date)
    list_url = tree.xpath('//ul[@class="clearfix"]/li/a')
    for i in list_url:
        url_img = i.xpath('./img/@src')
        que.put('https://pic.netbian.com' + str(*url_img))  # put写入进程变量队列中
    resp.close()

下载并保存图片

接下来,我们需要编写函数来下载并保存图片。我们使用requests库发送GET请求,然后将图片保存到本地。为了避免文件名冲突,我们可以使用一个共享的数值型变量来为每张图片分配一个唯一的文件名。这个变量会在多个进程之间共享,确保每张图片的文件名都不同。

# 下载并保存图片
def download_ove(url, name):
    try:
        resp = requests.get(url, headers=headers)
        path_img = os.path.join(path, f'{name.value}.jpg')
        with open(path_img, 'wb') as f:
            f.write(resp.content)
        print(f'保存成功{name.value}.jpg')
        name.value += 1  # 数值型进程变量自增
    except Exception as ex:
        print('下载出错', ex)

下载图片的主函数

现在,让我们来编写下载图片的主函数。我们使用了线程池来并发下载图片,这样可以提高下载速度。通过创建一个ThreadPoolExecutor对象,我们可以指定同时运行的线程数量,这里设置为20。然后,我们从进程队列中获取图片地址,并将下载任务提交给线程池处理。

# 获取进程队列中的url并启用线程池下载保存图片
def download_img(que, name):
    # 创建线程池,指定20个线程处理数据
    with ThreadPoolExecutor(20) as t:
        while True:
            try:
                s = que.get(timeout=3)  # 获取进程队列中的数据,等待3秒若是还没获取到数据抛出异常
                t.submit(download_ove, s, name)  # 添加进线程池
            except Exception as ec:
                print(ec)
                break

异常处理

在我们的代码中,我们还加入了异常处理机制。如果下载出现错误,我们会捕获异常并打印出错信息。这有助于我们及时发现问题并进行处理。

# 接收进程池与线程池异常的回调函数
def err_call_back(err):
    print(f'出错啦~ error:{str(err)}')

执行主程序

最后,我们在主程序中执行上述函数。我们首先创建了一个进程共享的队列变量和一个数值型的共享变量,用于存储图片地址和文件名计数。然后,我们根据需要获取多个页面的图片地址,将下载任务提交给进程池,并等待任务完成。这样,我们就能够高效地下载大量图片了。

if __name__ == '__main__':
    if not os.path.exists(path):
        os.mkdir(path)
    que = multiprocessing.Manager().Queue()  # 创建一个进程之间共享的队列变量
    name = multiprocessing.Manager().Value('i', 0)  # 创建一个进程之间共享的数值型变量,'i'表示整型数字,0表示从0开始
    for i in range(1, 4):
        if i != 1:
            url = f'https://pic.netbian.com/4kdongman/index_{i}.html'
        else:
            url = 'https://pic.netbian.com/4kdongman/'
        get_url(url, que)
        #  创建进程池,并将函数添加到进程池内,指定最多开辟1个进程处理数据(开多了怕把网址玩崩)
        with multiprocessing.Pool(1) as pool:
            pool.apply(download_img, args=(que, name))  # 将函数以同步的方式添加进进程池
    pool.close()  # 结束进程池,不在往内添加数据
    pool.join()  # 等待进程池运行结束
    print('结束')

结束语

通过使用进程池和线程池的组合,我们能够高效地下载大量图片,提高了任务的并发性和效率。这种方法对于需要大规模获取图片数据的任务非常有用,例如构建图像数据集或爬取网站上的图片资源。

希望这个教程对你有所帮助,如果你有任何问题或建议,欢迎在评论中留言。祝愿你在图片下载任务中取得成功!

本文由作者 王大神 原创发布于 大神网的AI博客。

转载请注明作者:王大神

原文出处:从进程池到线程池:实现高效图片下载

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 2023年10月14日
下一篇 2023年10月14日

相关推荐

  • 动态类型语言中如何确定返回值类型:Python实践指南

    在Python的世界中,张三正面临一个挑战。他正在使用一个新的第三方库,但遇到了一个问题:每次调用函数,由于缺乏类型提示,他都不知道返回的数据类型是什么。看源码,但似乎很复杂,IDE没有给出有用的提示。张三开…

    2023年10月9日
    00
  • 如何解决PyCharm中的ModuleNotFoundError错误

    嗨,各位亲爱的程序开发者和数据科学家!你是否曾经在使用PyCharm编写Python程序时遇到过烦人的错误信息,特别是那个令人头痛的ModuleNotFoundError: No module named ‘XXX’?别担心,本教程将帮助你解决这个问题,…

    2023年9月25日
    00
  • 从VCF到CSV:将联系人数据格式转换的Python教程

    在数字化时代,我们经常需要在不同的应用程序和设备之间共享联系人信息。然而,不同的应用程序和设备可能使用不同的联系人数据格式,这可能会导致数据转换的问题。在这篇文章中,我将向你介绍如何使用Python来将.vc…

    2023年9月27日
    00
  • 自动学籍照片裁剪工具:一键裁剪满足规格的学籍照片

    学校、培训机构、教育部门等经常需要处理大量学生或员工的学籍照片。这些照片通常需要符合特定的规格,包括尺寸和头像的居中等要求。手动裁剪这些照片是一项繁琐的任务,但我们可以使用Python编写一个自动化工具来…

    2023年9月21日
    00
  • 如何使用Python爬取豆瓣电影Top250的电影海报

    作为一位电影爱好者,你可能经常关注豆瓣电影上的Top250电影榜单,想要了解哪些电影备受推崇。而且,你可能也希望将一些你喜欢的电影的海报保存下来,以便日后欣赏或分享。但是,手动一个一个点击电影,然后下载海…

    2023年9月21日
    00
  • 从Java到Python:数据分析新征程的启航

    在现代科技领域,数据分析已经成为了一个不可或缺的部分。对于那些原本从事Java编程的开发者来说,转向Python并掌握数据分析技能可能是一项重要的挑战。本文将探讨从Java到Python的转变,以及如何开始学习Python的…

    2023年10月27日
    00
  • 如何使用Python减轻工作压力和自动化任务:从会计、教师到销售的全能工具

    在当今繁忙的工作环境中,提高效率和减轻工作压力是每个行业都面临的挑战。无论您是一名会计师、教师还是销售专业人员,Python都可以成为您的得力助手,帮助您自动化任务、提高工作效率。在本教程中,我们将探讨Pyt…

    2023年10月20日
    00
  • 准时到达目的地:列车最小时速计算详解

    在快节奏的现代生活中,时间管理变得尤为重要。想象一下,你每天上班需要乘坐多趟列车,每趟列车都有固定的行驶距离和发车时间。如何计算出一个最合理的时速,以确保你准时到达办公室呢?这不仅是一个关于时间和速…

    2023年11月25日
    00
  • 教程:使用Python爬取抖音用户的视频

    嗨,各位技术爱好者和数据挖掘狂热者们!你是否曾经在抖音上看到一个超赞的用户,想要保存他们的视频以便离线观看?或者你是一位研究者,需要获取某个用户在一段时间内发布的所有视频?今天,我将带你进入一个令人…

    2023年10月24日
    00
  • 为什么Go不会重构成Java:性能、生态和生产环境考虑

    你是否曾想象过,随着JDK 21的更新,Go语言是否有可能在未来会重构成Java?虽然这种想法听起来有点奇怪,但让我们探讨一下这个问题,看看Java的最新特性和Go语言之间的性能差异是否可能改变这一情况。 开篇故事 故…

    2023年9月21日
    00