多线程下载图片
爬虫项目介绍
本次爬虫项目将爬取豆瓣Top250电影的图片,其网址为:https://movie.douban.com/top250, 具体页面如下图所示:
本次爬虫项目将分别不使用多线程和使用多线程来完成,通过两者的对比,显示出多线程在爬虫项目中的巨大优势。本文所使用的多线程用到了concurrent.futures模块,该模块是Python中最广为使用的并发库,它可以非常方便地将任务并行化。在concurrent.futures模块中,共有两种并发模块,分别如下:
- 多线程模式:ThreadPoolExecutor,适合 IO密集型任务;
- 多进程模式:ProcessPoolExecutor,适合计算密集型任务。
具体的关于该模块的介绍可以参考其官方网址:https://docs.python.org/3/library/concurrent.futures.html 。
本次爬虫项目将会用到concurrent.futures模块中的ThreadPoolExecutor类,多线程下载豆瓣Top250电影图片。下面将会给出本次爬虫项目分别不使用多线程和使用多线程的对比,以此来展示多线程在爬虫中的巨大优势。
不使用多线程
首先,我们不使用多线程来下载豆瓣Top250电影图片,其完整的Python代码如下:
import time import requests import urllib.request from bs4 import BeautifulSoup # 该函数用于下载图片 # 传入函数: 网页的网址url def download_picture(url): # 获取网页的源代码 r = requests.get(url) # 利用BeautifulSoup将获取到的文本解析成HTML soup = BeautifulSoup(r.text, "lxml") # 获取网页中的电影图片 content = soup.find('div', class_='article') images = content.find_all('img') # 获取电影图片的名称和下载地址 picture_name_list = [image['alt'] for image in images] picture_link_list = [image['src'] for image in images] # 利用urllib.request..urlretrieve正式下载图片 for picture_name, picture_link in zip(picture_name_list, picture_link_list): urllib.request.urlretrieve(picture_link, 'D://douban/%s.jpg' % picture_name) def main(): # 全部10个网页 start_urls = ["https://movie.douban.com/top250"] for i in range(1, 10): start_urls.append("https://movie.douban.com/top250?start=%d&filter=" % (25 * i)) # 统计该爬虫的消耗时间 t1 = time.time() print('*' * 50) for url in start_urls: download_picture(url) t2 = time.time() print('不使用多线程,总共耗时:%s'%(t2-t1)) print('*' * 50) main()
其输出结果如下:
去D盘中的douban文件夹查看,如下图:
我们可以看到,在不使用多线程的情况下,这个爬虫总共耗时约80s,完成了豆瓣Top250电影图片的下载。
使用多线程
接下来,我们使用多线程来下载豆瓣Top250电影图片,其完整的Python代码如下:
import time import requests import urllib.request from bs4 import BeautifulSoup from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED # 该函数用于下载图片 # 传入函数: 网页的网址url def download_picture(url): # 获取网页的源代码 r = requests.get(url) # 利用BeautifulSoup将获取到的文本解析成HTML soup = BeautifulSoup(r.text, "lxml") # 获取网页中的电影图片 content = soup.find('div', class_='article') images = content.find_all('img') # 获取电影图片的名称和下载地址 picture_name_list = [image['alt'] for image in images] picture_link_list = [image['src'] for image in images] # 利用urllib.request..urlretrieve正式下载图片 for picture_name, picture_link in zip(picture_name_list, picture_link_list): urllib.request.urlretrieve(picture_link, 'D://豆瓣/%s.jpg' % picture_name) def main(): # 全部10个网页 start_urls = ["https://movie.douban.com/top250"] for i in range(1, 10): start_urls.append("https://movie.douban.com/top250?start=%d&filter=" % (25 * i)) # 统计该爬虫的消耗时间 print('*' * 50) t3 = time.time() # 利用并发下载电影图片 executor = ThreadPoolExecutor(max_workers=10) # 可以自己调整max_workers,即线程的个数 # submit()的参数: 第一个为函数, 之后为该函数的传入参数,允许有多个 future_tasks = [executor.submit(download_picture, url) for url in start_urls] # 等待所有的线程完成,才进入后续的执行 wait(future_tasks, return_when=ALL_COMPLETED) t4 = time.time() print('使用多线程,总共耗时:%s' % (t4 - t3)) print('*' * 50) main()
其输出结果如下:
再去D盘中的douban文件夹查看,发现同样也下载了250张电影图片。
总结
通过上述两个爬虫程序的对比,我们不难发现,同样是下载豆瓣Top250电影,10个网页中的图片,在没有使用多线程的情况下,总共耗时约80s,而在使用多线程(10个线程)的情况下,总共耗时约9.5秒,效率整整提高了约8倍。这样的效率提升在爬虫中无疑是令人兴奋的。
大名鼎鼎的Python爬虫框架Scrapy!
原文地址:https://www.cnblogs.com/chen8023miss/p/11430909.html
- JavaScript 学习一
- 与Ajax同样重要的jQuery(2)
- 寻找第K元素的八大算法、源码及拓展
- 索引优先队列-IndexedPrirotyQueue的原理及实现(源码)
- Java 集合系列02之 Collection架构
- 开发者需要掌握的JS事件
- Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
- Kosaraju算法、Tarjan算法分析及证明--强连通分量的线性算法
- 关于curl网站运维与开发的那些事
- 并查集Union-find及其在最小生成树中的应用
- go 语言的库文件放在哪里?如何通过nginx代理后还能正确获取远程地址
- 离线Tarjan算法-最近公共祖先问题
- Java文件上传下载实训
- 【网络编程系列】二:socket通信原理及实践
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Django之choices选项和富文本编辑器的使用详解
- Android使用RSA加密和解密的示例代码
- Android布局之帧布局FrameLayout详解
- Okhttp3实现爬取验证码及获取Cookie的示例
- Android监听系统来电并弹出提示窗口
- 你该知道的Gradle配置知识总结
- Android布局之绝对布局AbsoluteLayout详解
- django实现模型字段动态choice的操作
- 详解ASP.NET Core 处理 404 Not Found
- Python AutoCAD 系统设置的实现方法
- Python如何操作office实现自动化及win32com.client的运用
- android Palette调色板使用详解
- python 穷举指定长度的密码例子
- Android 高仿微信朋友圈拍照上传功能
- android的ListView点击item使item展开的做法的实现代码