Python3多线程爬虫实例讲解代码


Posted in Python onJanuary 05, 2018

多线程概述

多线程使得程序内部可以分出多个线程来做多件事情,充分利用CPU空闲时间,提升处理效率。python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点,在threading 得到了弥补。并且在Python3中废弃了thread模块,保留了更强大的threading模块。

使用场景

在python的原始解释器CPython中存在着GIL(Global Interpreter Lock,全局解释器锁),因此在解释执行python代码时,会产生互斥锁来限制线程对共享资源的访问,直到解释器遇到I/O操作或者操作次数达到一定数目时才会释放GIL。所以,虽然CPython的线程库直接封装了系统的原生线程,但CPython整体作为一个进程,同一时间只会有一个获得GIL的线程在跑,其他线程则处于等待状态。这就造成了即使在多核CPU中,多线程也只是做着分时切换而已。

如果你的程序是CPU密集型,多个线程的代码很有可能是线性执行的。所以这种情况下多线程是鸡肋,效率可能还不如单线程因为有上下文切换开销。但是如果你的代码是IO密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,多线程可以明显提高效率,例如多线程爬虫,多线程文件处理等等

多线程爬虫

多线程爬虫的代码实例

注: 以下代码在python3下运行通过, python2版本差异较大,不能运行成功,如需帮助请下方留意。

# coding=utf-8
import threading, queue, time, urllib
from urllib import request
baseUrl = 'http://www.pythontab.com/html/pythonjichu/'
urlQueue = queue.Queue()
for i in range(2, 10):
 url = baseUrl + str(i) + '.html'
 urlQueue.put(url)
 #print(url)
def fetchUrl(urlQueue):
 while True:
  try:
   #不阻塞的读取队列数据
   url = urlQueue.get_nowait()
   i = urlQueue.qsize()
  except Exception as e:
   break
  print ('Current Thread Name %s, Url: %s ' % (threading.currentThread().name, url))
  try:
   response = urllib.request.urlopen(url)
   responseCode = response.getcode()
  except Exception as e:
   continue
  if responseCode == 200:
   #抓取内容的数据处理可以放到这里
   #为了突出效果, 设置延时
   time.sleep(1)
if __name__ == '__main__':
 startTime = time.time()
 threads = []
 # 可以调节线程数, 进而控制抓取速度
 threadNum = 4
 for i in range(0, threadNum):
  t = threading.Thread(target=fetchUrl, args=(urlQueue,))
  threads.append(t)
 for t in threads:
  t.start()
 for t in threads:
  #多线程多join的情况下,依次执行各线程的join方法, 这样可以确保主线程最后退出, 且各个线程间没有阻塞
  t.join()
 endTime = time.time()
 print ('Done, Time cost: %s ' % (endTime - startTime))

运行结果:

1个线程时:

Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/2.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/3.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/4.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/5.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/6.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/7.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/8.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/9.html 
Done, Time cost: 8.182249069213867

2个线程时:

Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/2.html 
Current Thread Name Thread-2, Url: http://www.pythontab.com/html/pythonjichu/3.html 
Current Thread Name Thread-2, Url: http://www.pythontab.com/html/pythonjichu/4.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/5.html 
Current Thread Name Thread-2, Url: http://www.pythontab.com/html/pythonjichu/6.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/7.html 
Current Thread Name Thread-2, Url: http://www.pythontab.com/html/pythonjichu/8.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/9.html 
Done, Time cost: 4.0987958908081055

3个线程时:

Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/2.html 
Current Thread Name Thread-2, Url: http://www.pythontab.com/html/pythonjichu/3.html 
Current Thread Name Thread-3, Url: http://www.pythontab.com/html/pythonjichu/4.html 
Current Thread Name Thread-4, Url: http://www.pythontab.com/html/pythonjichu/5.html 
Current Thread Name Thread-2, Url: http://www.pythontab.com/html/pythonjichu/6.html 
Current Thread Name Thread-4, Url: http://www.pythontab.com/html/pythonjichu/7.html 
Current Thread Name Thread-1, Url: http://www.pythontab.com/html/pythonjichu/9.html 
Current Thread Name Thread-3, Url: http://www.pythontab.com/html/pythonjichu/8.html 
Done, Time cost: 2.287320137023926

通过调节线程数可以看到,执行时间会随着线程数的增加而缩短,抓取效率成正比增加。

总结:

Python多线程在IO密集型任务,多线程可以明显提高效率,CPU密集型任务不适合使用多线程处理。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现word 2007文档转换为pdf文件
Mar 15 Python
Python迭代器与生成器基本用法分析
Jul 26 Python
pyqt5的QComboBox 使用模板的具体方法
Sep 06 Python
Python 获取中文字拼音首个字母的方法
Nov 28 Python
浅析Python与Mongodb数据库之间的操作方法
Jul 01 Python
python可视化篇之流式数据监控的实现
Aug 07 Python
Django与pyecharts结合的实例代码
May 13 Python
Python简单实现词云图代码及步骤解析
Jun 04 Python
记录一下scrapy中settings的一些配置小结
Sep 28 Python
scrapy-redis分布式爬虫的搭建过程(理论篇)
Sep 29 Python
PyTorch梯度裁剪避免训练loss nan的操作
May 24 Python
变长双向rnn的正确使用姿势教学
May 31 Python
python编写微信远程控制电脑的程序
Jan 05 #Python
使用python爬虫实现网络股票信息爬取的demo
Jan 05 #Python
简单实现python收发邮件功能
Jan 05 #Python
5款非常棒的Python工具
Jan 05 #Python
Python基于列表模拟堆栈和队列功能示例
Jan 05 #Python
Django 2.0版本的新特性抢先看!
Jan 05 #Python
微信跳一跳游戏python脚本
Apr 01 #Python
You might like
PHP脚本的10个技巧(4)
2006/10/09 PHP
PHP开发Apache服务器配置
2015/07/15 PHP
PHP定义字符串的四种方式详解
2018/02/06 PHP
jquery中的sortable排序之后的保存状态的解决方法
2010/01/28 Javascript
js 无提示关闭浏览器页面的代码
2010/03/09 Javascript
Iframe自适应高度绝对好使的代码 兼容IE,遨游,火狐
2011/01/27 Javascript
jQuery中live方法的重复绑定说明
2011/10/21 Javascript
DIV外区域Click后关闭DIV的实现代码
2011/12/21 Javascript
jQuery 顶部导航跟随滚动条滚动固定浮动在顶部
2014/06/06 Javascript
JS使用oumousemove和oumouseout动态改变图片显示的方法
2015/03/31 Javascript
JS实现简单的二元方程计算器功能示例
2017/01/03 Javascript
微信小程序页面间通信的5种方式
2017/03/31 Javascript
深入浅析Node.js 事件循环、定时器和process.nextTick()
2018/10/22 Javascript
小程序登录/注册页面设计的实现代码
2019/05/24 Javascript
vue中解决微信html5原生ios虚拟键返回不刷新问题
2020/10/20 Javascript
vue element-ul实现展开和收起功能的实例代码
2020/11/25 Vue.js
[02:53]DOTA2英雄基础教程 山岭巨人小小
2013/12/09 DOTA
[13:25]VP vs VICI (BO3)
2018/06/07 DOTA
python3批量删除豆瓣分组下的好友的实现代码
2016/06/07 Python
python利用拉链法实现字典方法示例
2017/03/25 Python
基于python神经卷积网络的人脸识别
2018/05/24 Python
python numpy 显示图像阵列的实例
2018/07/02 Python
python利用datetime模块计算程序运行时间问题
2020/02/20 Python
html5触摸事件判断滑动方向的实现
2018/06/05 HTML / CSS
Revolution Beauty美国官网:英国知名化妆品网站
2018/07/23 全球购物
暑期实践思想汇报
2014/01/06 职场文书
参观考察邀请函范文
2014/01/29 职场文书
开业庆典策划方案
2014/02/18 职场文书
政府绩效管理实施方案
2014/05/04 职场文书
乔布斯斯坦福大学演讲稿
2014/05/23 职场文书
卫生院健康教育实施方案
2014/06/07 职场文书
乡镇群众路线教育实践活动整改措施
2014/10/04 职场文书
入党转正申请报告
2015/05/15 职场文书
班主任经验交流心得体会
2015/11/02 职场文书
PyQt5实现多张图片显示并滚动
2021/06/11 Python
Golang表示枚举类型的详细讲解
2021/09/04 Golang