Python爬虫之线程池的使用

作者:世界的隐喻 时间:2021-04-08 20:01:01 

一、前言

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

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

Python爬虫之线程池的使用

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

三、异步,线程池代码

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


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)

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

Python爬虫之线程池的使用

我们发现这次我们的运行时间只用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)

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

Python爬虫之线程池的使用

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

五、使用线程池的异步爬虫爬取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)

让我们来看看运行的结果

Python爬虫之线程池的使用

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

注意

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

来源:https://blog.csdn.net/ShiJieDeYinYu/article/details/116608974

标签:python,线程池,爬虫
0
投稿

猜你喜欢

  • Python自动生成代码 使用tkinter图形化操作并生成代码框架

    2021-04-26 08:47:30
  • 这三个好用的python函数你不能不知道!

    2023-04-23 10:29:22
  • 浅析python中特殊文件和特殊函数

    2023-01-22 23:26:26
  • OpenCV+python实现膨胀和腐蚀的示例

    2021-06-12 10:35:00
  • Python中DataFrame与内置数据结构相互转换的实现

    2022-12-09 18:17:55
  • 如何将计数器的值赋给一个变量?

    2009-12-03 20:02:00
  • Python 调用 Outlook 发送邮件过程解析

    2023-11-17 19:34:57
  • 一文详解Python中复合语句的用法

    2021-08-11 23:15:40
  • 详解Python如何实现Excel数据读取和写入

    2023-10-29 06:46:35
  • python获取list下标及其值的简单方法

    2023-09-18 08:30:56
  • 操作Dom节点实现间歇滚动新闻

    2009-10-16 20:51:00
  • python 3.7.0 安装配置方法图文教程

    2023-10-14 22:24:28
  • 关于H1的位置

    2008-04-30 12:20:00
  • 利用phpExcel实现Excel数据的导入导出(全步骤详细解析)

    2023-06-22 02:56:42
  • python实现猜拳游戏项目

    2023-02-25 15:15:30
  • Django框架CBV装饰器中间件auth模块CSRF跨站请求问题

    2021-03-25 09:42:01
  • 深入理解Python 多线程

    2021-03-25 05:25:28
  • linux环境下安装python虚拟环境及注意事项

    2023-12-09 08:02:47
  • python实现四舍五入方式

    2021-01-17 01:39:33
  • 在Python下利用OpenCV来旋转图像的教程

    2022-12-18 22:53:46
  • asp之家 网络编程 m.aspxhome.com