使用多线程或异步技术提高图片抓取效率

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时计算 Flink 版,5000CU*H 3个月
简介: 图片抓取是爬虫技术中常见的需求,但是图片抓取的效率受到很多因素的影响,比如网速、网站反爬机制、图片数量和大小等。本文将介绍如何使用多线程或异步技术来提高图片抓取的效率,以及如何使用爬虫代理IP来避免被网站拒绝服务

亿牛云代理.jpg

导语

图片抓取是爬虫技术中常见的需求,但是图片抓取的效率受到很多因素的影响,比如网速、网站反爬机制、图片数量和大小等。本文将介绍如何使用多线程或异步技术来提高图片抓取的效率,以及如何使用爬虫代理IP来避免被网站封禁。

概述

多线程和异步技术都是利用计算机的并发能力来提高程序的执行速度。多线程是指在一个进程中创建多个线程,每个线程可以独立地执行一部分任务,从而实现任务的并行处理。异步技术是指在一个线程中使用非阻塞的方式来执行任务,当遇到耗时的操作时,不会等待其完成,而是继续执行其他任务,从而实现任务的并发处理。使用多线程或异步技术可以有效地减少图片抓取的等待时间,提高图片抓取的效率。爬虫代理IP是指通过第三方服务器来访问目标网站,从而隐藏自己的真实IP地址。使用爬虫代理IP可以有效地防止被目标网站识别和封禁,提高图片抓取的成功率。

正文

本文将以Python语言为例,介绍如何使用多线程或异步技术来实现图片抓取,并使用亿牛云爬虫代理来提供代理IP服务。首先,需要导入一些必要的模块,如requests、threading、asyncio、aiohttp等:

# 导入模块
import requests
import threading
import asyncio
import aiohttp

然后,需要定义一个函数来获取图片的URL列表,这里假设目标网站是https://unsplash.com/,一个提供免费高清图片的网站。可以使用requests模块来发送HTTP请求,并使用BeautifulSoup模块来解析HTML文档,提取图片的URL:

# 定义函数获取图片URL列表
def get_image_urls():
    # 目标网站URL
    url = 'https://unsplash.com/'
    # 亿牛云 爬虫代理域名、端口、用户名、密码
    proxy_host = 'http://www.16yun.cn'
    proxy_port = '8080'
    proxy_user = '16YUN'
    proxy_pass = '16IP'
    # 构造代理URL
    proxy_url = f'{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}'
    # 构造代理字典
    proxies = {
   
   
        'http': proxy_url,
        'https': proxy_url
    }
    # 发送HTTP请求,获取响应内容
    response = requests.get(url, proxies=proxies)
    html = response.text
    # 解析HTML文档,提取图片URL
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, 'lxml')
    images = soup.find_all('img', class_='oCCRx')
    image_urls = [image['src'] for image in images]
    # 返回图片URL列表
    return image_urls

接下来,需要定义一个函数来下载并保存图片,这里假设将图片保存在当前目录下的images文件夹中。可以使用requests模块来下载图片,并使用os模块来创建文件夹和文件:

# 定义函数下载并保存图片
def download_and_save_image(image_url):
    # 亿牛云 爬虫代理域名、端口、用户名、密码
    proxy_host = 'http://www.16yun.cn'
    proxy_port = '8080'
    proxy_user = '16YUN'
    proxy_pass = '16IP'
    # 构造代理URL
    proxy_url = f'{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}'
    # 构造代理字典
    proxies = {
   
   
        'http': proxy_url,
        'https': proxy_url
    }
    # 下载图片,获取图片内容
    response = requests.get(image_url, proxies=proxies)
    image_data = response.content
    # 创建images文件夹,如果不存在
    import os
    if not os.path.exists('images'):
        os.mkdir('images')
    # 从图片URL中提取图片文件名
    image_name = image_url.split('/')[-1]
    # 拼接图片文件路径
    image_path = os.path.join('images', image_name)
    # 保存图片文件
    with open(image_path, 'wb') as f:
        f.write(image_data)

最后,需要定义一个主函数来调用上述两个函数,并使用多线程或异步技术来提高图片抓取的效率。这里分别介绍两种方法:

  • 使用多线程技术:可以使用threading模块来创建多个线程对象,并将下载并保存图片的函数作为线程的目标函数,将图片URL作为线程的参数,然后启动所有线程,并等待所有线程结束:
# 定义主函数使用多线程技术
def main_threading():
    # 获取图片URL列表
    image_urls = get_image_urls()
    # 创建空列表存储线程对象
    threads = []
    # 遍历图片URL列表,创建并启动线程对象
    for image_url in image_urls:
        # 创建线程对象,指定目标函数和参数
        thread = threading.Thread(target=download_and_save_image, args=(image_url,))
        # 将线程对象添加到列表中
        threads.append(thread)
        # 启动线程对象
        thread.start()
    # 遍历线程对象列表,等待所有线程结束
    for thread in threads:
        thread.join()
  • 使用异步技术:可以使用asyncio模块来创建一个事件循环对象,并将下载并保存图片的函数改写为一个异步函数,使用aiohttp模块来发送异步HTTP请求,并使用asyncio模块的gather函数来收集所有的异步任务,并在事件循环中执行:
# 定义主函数使用异步技术
def main_asyncio():
    # 获取图片URL列表
    image_urls = get_image_urls()
    # 创建事件循环对象
    loop = asyncio.get_event_loop()
    # 定义异步函数下载并保存图片
    async def download_and_save_image_async(image_url):
        # 亿牛云 爬虫代理域名、端口、用户名、密码
        proxy_host = 'http://www.16yun.cn'
        proxy_port = '8080'
        proxy_user = '16YUN'
        proxy_pass = '16IP'
        # 构造代理URL
        proxy_url = f'{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}'
        # 构造代理字典
        proxies = {
   
   
            'http': proxy_url,
            'https': proxy_url
        }
        # 使用aiohttp模块发送异步HTTP请求,获取图片内容
        async with aiohttp.ClientSession() as session:
            async with session.get(image_url, proxy=proxy_url) as response:
                image_data = await response.read()
        # 创建images文件夹,如果不存在
        import os
        if not os.path.exists('images'):
            os.mkdir('images')
        # 从图片URL中提取图片文件名
        image_name = image_url.split('/')[-1]
        # 拼接图片文件路径
        image_path = os.path.join('images', image_name)
        # 保存图片文件
        with open(image_path, 'wb') as f:
            f.write(image_data)
    # 创建空列表存储异步任务对象
    tasks = []
    # 遍历图片URL列表,创建并添加异步任务对象
    for image_url in image_urls:
        # 创建异步任务对象,指定异步函数和参数
        task = asyncio.ensure_future(download_and_save_image_async(image_url))
        # 将异步任务对象添加到列表中
        tasks.append(task)
    # 使用asyncio模块的gather函数收集所有的异步任务对象
    tasks = asyncio.gather(*tasks)
    # 在事件循环中执行所有的异步任务对象,并等待其完成
    loop.run_until_complete(tasks)

结语

本文介绍了如何使用多线程或异步技术来提高图片抓取的效率,以及如何使用代理IP来避免被网站封禁。通过使用多线程或异步技术,可以有效地减少图片抓取的等待时间,提高图片抓取的效率。通过使用代理IP,可以有效地防止被目标网站识别和封禁,提高图片抓取的成功率。本文以Python语言为例,给出了相应的代码实现,供读者参考。

相关文章
|
1月前
|
编解码 数据安全/隐私保护 计算机视觉
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
如何使用OpenCV进行同步和异步操作来打开海康摄像头,并提供了相关的代码示例。
91 1
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
|
4月前
|
安全 Python
告别低效编程!Python线程与进程并发技术详解,让你的代码飞起来!
【7月更文挑战第9天】Python并发编程提升效率:**理解并发与并行,线程借助`threading`模块处理IO密集型任务,受限于GIL;进程用`multiprocessing`实现并行,绕过GIL限制。示例展示线程和进程创建及同步。选择合适模型,注意线程安全,利用多核,优化性能,实现高效并发编程。
75 3
|
1月前
|
安全 调度 C#
STA模型、同步上下文和多线程、异步调度
【10月更文挑战第19天】本文介绍了 STA 模型、同步上下文和多线程、异步调度的概念及其优缺点。STA 模型适用于单线程环境,确保资源访问的顺序性;同步上下文和多线程提高了程序的并发性和响应性,但增加了复杂性;异步调度提升了程序的响应性和资源利用率,但也带来了编程复杂性和错误处理的挑战。选择合适的模型需根据具体应用场景和需求进行权衡。
|
1月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
66 0
|
2月前
|
设计模式 缓存 Java
谷粒商城笔记+踩坑(14)——异步和线程池
初始化线程的4种方式、线程池详解、异步编排 CompletableFuture
谷粒商城笔记+踩坑(14)——异步和线程池
|
3月前
|
缓存 Java
异步&线程池 线程池的七大参数 初始化线程的4种方式 【上篇】
这篇文章详细介绍了Java中线程的四种初始化方式,包括继承Thread类、实现Runnable接口、实现Callable接口与FutureTask结合使用,以及使用线程池。同时,还深入探讨了线程池的七大参数及其作用,解释了线程池的运行流程,并列举了四种常见的线程池类型。最后,阐述了在开发中使用线程池的原因,如降低资源消耗、提高响应速度和增强线程的可管理性。
异步&线程池 线程池的七大参数 初始化线程的4种方式 【上篇】
|
3月前
|
Java 数据库
异步&线程池 CompletableFuture 异步编排 实战应用 【终结篇】
这篇文章通过一个电商商品详情页的实战案例,展示了如何使用`CompletableFuture`进行异步编排,以解决在不同数据库表中查询商品信息的问题,并提供了详细的代码实现和遇到问题(如图片未显示)的解决方案。
异步&线程池 CompletableFuture 异步编排 实战应用 【终结篇】
|
2月前
|
监控 Java
线程池中线程异常后:销毁还是复用?技术深度剖析
在并发编程中,线程池作为一种高效利用系统资源的工具,被广泛用于处理大量并发任务。然而,当线程池中的线程在执行任务时遇到异常,如何妥善处理这些异常线程成为了一个值得深入探讨的话题。本文将围绕“线程池中线程异常后:销毁还是复用?”这一主题,分享一些实践经验和理论思考。
135 3
|
3月前
|
API Windows
揭秘网络通信的魔法:Win32多线程技术如何让服务器化身超级英雄,同时与成千上万客户端对话!
【8月更文挑战第16天】在网络编程中,客户/服务器模型让客户端向服务器发送请求并接收响应。Win32 API支持在Windows上构建此类应用。首先要初始化网络环境并通过`socket`函数创建套接字。服务器需绑定地址和端口,使用`bind`和`listen`函数准备接收连接。对每个客户端调用`accept`函数并在新线程中处理。客户端则通过`connect`建立连接,双方可通过`send`和`recv`交换数据。多线程提升服务器处理能力,确保高效响应。
56 6
|
3月前
|
Java
异步&线程池 CompletableFuture 异步编排 【下篇】
这篇文章深入探讨了Java中的`CompletableFuture`类,解释了如何创建异步操作、使用计算完成时的回调方法、异常处理、串行化方法、任务组合以及多任务组合的使用方式,并通过代码示例展示了各种场景下的应用。
异步&线程池 CompletableFuture 异步编排 【下篇】