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益智游戏计算汉诺塔问题示例
Mar 05 Python
python动态加载包的方法小结
Apr 18 Python
Python中动态检测编码chardet的使用教程
Jul 06 Python
Python实现进程同步和通信的方法
Jan 02 Python
Python 实现「食行生鲜」签到领积分功能
Sep 26 Python
python 实现调用子文件下的模块方法
Dec 07 Python
PyQt5 实现给窗口设置背景图片的方法
Jun 13 Python
Python Django框架模板渲染功能示例
Nov 08 Python
Python运行异常管理解决方案
Mar 09 Python
python实现mean-shift聚类算法
Jun 10 Python
详解pytorch中squeeze()和unsqueeze()函数介绍
Sep 03 Python
Python extract及contains方法代码实例
Sep 11 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自动生成后台导航网址的最佳方法
2013/08/27 PHP
PHP中把对象转换为关联数组代码分享
2015/04/09 PHP
PHP PDOStatement::bindValue讲解
2019/01/30 PHP
用cookies实现的可记忆的样式切换效果代码下载
2007/12/24 Javascript
QUnit jQuery的TDD框架
2010/11/04 Javascript
jQuery中next方法用法实例
2015/04/24 Javascript
jQuery支持添加事件的日历特效代码分享(3种样式)
2015/08/24 Javascript
基于JavaScript实现文字超出部分隐藏
2016/02/29 Javascript
Node.js的环境安装配置(使用nvm方式)
2016/10/11 Javascript
js原生实现FastClick事件的实例
2016/11/20 Javascript
AngularJS入门教程之Helloworld示例
2016/12/25 Javascript
js实现自定义进度条效果
2017/03/15 Javascript
vue2的todolist入门小项目的详细解析
2017/05/11 Javascript
详解如何使用Node.js编写命令工具——以vue-cli为例
2017/06/29 Javascript
JavaScript判断日期时间差的实例代码
2018/03/01 Javascript
vue展示dicom文件医疗系统的实现代码
2018/08/27 Javascript
详解JavaScript中精度失准问题及解决方法
2020/02/04 Javascript
vant中的toast轻提示实现代码
2020/11/04 Javascript
[02:55]2018DOTA2国际邀请赛勇士令状不朽珍藏Ⅲ饰品一览
2018/08/01 DOTA
对python 操作solr索引数据的实例详解
2018/12/07 Python
Python计算一个点到所有点的欧式距离实现方法
2019/07/04 Python
Python使用百度翻译开发平台实现英文翻译为中文功能示例
2019/08/08 Python
Python搭建Keras CNN模型破解网站验证码的实现
2020/04/07 Python
JAVA SWT事件四种写法实例解析
2020/06/05 Python
分享PyCharm最新激活码(真永久激活方法)不用每月找安装参数或最新激活码了
2020/12/27 Python
用pushplus+python监控亚马逊到货动态推送微信
2021/01/29 Python
css3的transition效果和transfor效果示例介绍
2013/10/30 HTML / CSS
美国知名的摄影器材销售网站:Adorama
2017/02/01 全球购物
阿波罗盒子:Apollo Box
2017/08/14 全球购物
PHP面试题集
2016/12/18 面试题
经济信息系毕业生自荐信范文
2014/03/15 职场文书
幼儿园保育员岗位职责
2014/04/13 职场文书
2014年人事部工作总结
2014/12/03 职场文书
2015年七一建党节活动总结
2015/03/20 职场文书
教你使用TensorFlow2识别验证码
2021/06/11 Python
Java使用JMeter进行高并发测试
2021/11/23 Java/Android