• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Python爬虫之线程池的使用

    一、前言

    学到现在,我们可以说已经学习了爬虫的基础知识,如果没有那些奇奇怪怪的反爬虫机制,基本上只要有时间分析,一般的数据都是可以爬取的,那么到了这个时候我们需要考虑的就是爬取的效率了,关于提高爬虫效率,也就是实现异步爬虫,我们可以考虑以下两种方式:一是线程池的使用(也就是实现单进程下的多线程),一是协程的使用(如果没有记错,我所使用的协程模块是从python3.4以后引入的,我写博客时使用的python版本是3.9)。

    今天我们先来讲讲线程池。

    二、同步代码演示

    我们先用普通的同步的形式写一段代码

    import time
    
    def func(url):
        print("正在下载:", url)
        time.sleep(2)
        print("下载完成:", url)
    
    if __name__ == '__main__':
        start = time.time() # 开始时间
    
        url_list = [
            "a", "b", "c"
        ]
    
        for url in url_list:
            func(url)
    
        end = time.time() # 结束时间
    
        print(end - start)
    

    对于代码运行的结果我们心里都有数,但还是让我们来看一下吧

    不出所料。运行时间果然是六秒

    三、异步,线程池代码

    那么如果我们使用线程池运行上述代码又会怎样呢?

    import time
    from multiprocessing import Pool
    
    def func(url):
        print("正在下载:", url)
        time.sleep(2)
        print("下载完成:", url)
    
    if __name__ == '__main__':
        start = time.time() # 开始时间
    
        url_list = [
            "a", "b", "c"
        ]
    
        pool = Pool(len(url_list)) # 实例化一个线程池对象,并且设定线程池的上限数量为列表长度。不设置上限也可以。
    
        pool.map(func, url_list)
    
        end = time.time() # 结束时间
    
        print(end - start)
    

    下面就是见证奇迹的时候了,让我们运行程序

    我们发现这次我们的运行时间只用2~3秒。其实我们可以将线程池简单的理解为将多个任务同时进行。

    注意:

    1.我使用的是 pycharm,如果使用的是 VS 或者说是 python 自带的 idle,在运行时我们只能看到最后时间的输出。

    2.我们输出结果可能并不是按 abc 的顺序输出的。

    四、同步爬虫爬取图片

    因为我们的重点是线程池的爬取效率提高,我们就简单的爬取一页的图片。

    import requests
    import time
    import os
    from lxml import etree
    
    def save_photo(url, title):
        # UA伪装
        header = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
        }
    
        # 发送请求
        photo = requests.get(url=url, headers=header).content
    
        # 创建路径,避免重复下载
        if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬虫爬取4K美女图片\\" + title + ".jpg"):
            with open("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬虫爬取4K美女图片\\" + title + ".jpg", "wb") as fp:
                print(title, "开始下载!!!")
                fp.write(photo)
                print(title, "下载完成!!!")
    
    if __name__ == '__main__':
        start = time.time()
    
        # 创建文件夹
        if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬虫爬取4K美女图片"):
            os.mkdir("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬虫爬取4K美女图片")
    
        # UA伪装
        header = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
        }
    
        # 指定url
        url = "https://pic.netbian.com/4kmeinv/"
    
        # 发送请求,获取源码
        page = requests.get(url = url, headers = header).text
    
        # xpath 解析,获取图片的下载地址的列表
        tree = etree.HTML(page)
        url_list = tree.xpath('//*[@id="main"]/div[3]/ul/li/a/@href')
        # 通过下载地址获取高清图片的地址和图片名称
        for href in url_list:
            new_url = "https://pic.netbian.com" + href
            # 再一次发送请求
            page = requests.get(url = new_url, headers = header).text
            # 再一次 xpath 解析
            new_tree = etree.HTML(page)
            src = "https://pic.netbian.com" + new_tree.xpath('//*[@id="img"]/img/@src')[0]
            title = new_tree.xpath('//*[@id="img"]/img/@title')[0].split(" ")[0]
            # 编译文字
            title = title.encode("iso-8859-1").decode("gbk")
            # 下载,保存
            save_photo(src, title)
    
        end = time.time()
        print(end - start)
    

    让我们看看同步爬虫需要多长时间

    然后再让我们看看使用线程池的异步爬虫爬取这些图片需要多久

    五、使用线程池的异步爬虫爬取4K美女图片

    import requests
    import time
    import os
    from lxml import etree
    from multiprocessing import Pool
    
    def save_photo(src_title):
        # UA伪装
        header = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
        }
    
        # 发送请求
        url = src_title[0]
        title = src_title[1]
        photo = requests.get(url=url, headers=header).content
    
        # 创建路径,避免重复下载
        if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬虫爬取4K美女图片\\" + title + ".jpg"):
            with open("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬虫爬取4K美女图片\\" + title + ".jpg", "wb") as fp:
                print(title, "开始下载!!!")
                fp.write(photo)
                print(title, "下载完成!!!")
    
    if __name__ == '__main__':
        start = time.time()
    
        # 创建文件夹
        if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬虫爬取4K美女图片"):
            os.mkdir("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬虫爬取4K美女图片")
    
        # UA伪装
        header = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
        }
    
        # 指定url
        url = "https://pic.netbian.com/4kmeinv/"
    
        # 发送请求,获取源码
        page = requests.get(url = url, headers = header).text
    
        # xpath 解析,获取图片的下载地址的列表
        tree = etree.HTML(page)
        url_list = tree.xpath('//*[@id="main"]/div[3]/ul/li/a/@href')
        # 存储最后的网址和标题的列表
        src_list = []
        title_list = []
        # 通过下载地址获取高清图片的地址和图片名称
        for href in url_list:
            new_url = "https://pic.netbian.com" + href
            # 再一次发送请求
            page = requests.get(url = new_url, headers = header).text
            # 再一次 xpath 解析
            new_tree = etree.HTML(page)
            src = "https://pic.netbian.com" + new_tree.xpath('//*[@id="img"]/img/@src')[0]
            src_list.append(src)
            title = new_tree.xpath('//*[@id="img"]/img/@title')[0].split(" ")[0]
            # 编译文字
            title = title.encode("iso-8859-1").decode("gbk")
            title_list.append(title)
    
        # 下载,保存。使用线程池
        pool = Pool()
        src_title = zip(src_list, title_list)
        pool.map(save_photo, list(src_title))
    
        end = time.time()
        print(end - start)
    

    让我们来看看运行的结果

    只用了 17 秒,可不要小瞧这几秒,如果数据太大,这些差距后来就会更大了。

    注意

    不过我们必须要明白 线程池 是有上限的,这就是说数据太大,线程池的效率也会降低,所以这就要用到协程模块了。

    到此这篇关于Python爬虫之线程池的使用的文章就介绍到这了,更多相关Python线程池的使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • Python 线程池模块之多线程操作代码
    • python线程池的四种好处总结
    • python爬虫线程池案例详解(梨视频短视频爬取)
    • python线程池 ThreadPoolExecutor 的用法示例
    • 实例代码讲解Python 线程池
    • Python 如何创建一个线程池
    • python线程池如何使用
    • 解决python ThreadPoolExecutor 线程池中的异常捕获问题
    • Python定时器线程池原理详解
    • Python 使用threading+Queue实现线程池示例
    • Python线程池的正确使用方法
    上一篇:python高级语法之闭包和装饰器详解
    下一篇:python实战之利用pygame实现贪吃蛇游戏(一)
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Python爬虫之线程池的使用 Python,爬虫,之,线程,池,的,