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入门篇之函数
Oct 20 Python
python判断给定的字符串是否是有效日期的方法
May 13 Python
基于Python Shell获取hostname和fqdn释疑
Jan 25 Python
Python字符串格式化的方法(两种)
Sep 19 Python
Python使用matplotlib的pie函数绘制饼状图功能示例
Jan 08 Python
Python cookbook(数据结构与算法)字典相关计算问题示例
Feb 18 Python
详谈python在windows中的文件路径问题
Apr 28 Python
django1.11.1 models 数据库同步方法
May 30 Python
不到40行代码用Python实现一个简单的推荐系统
May 10 Python
关于PyTorch 自动求导机制详解
Aug 18 Python
python3环境搭建过程(利用Anaconda+pycharm)完整版
Aug 19 Python
python Matplotlib模块的使用
Sep 16 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实现从ftp服务器上下载文件树到本地电脑的程序
2009/02/10 PHP
用C/C++扩展你的PHP 为你的php增加功能
2012/09/06 PHP
PHP时间格式控制符对照表分享
2013/07/23 PHP
php使用curl抓取qq空间的访客信息示例
2014/02/28 PHP
php实现数组筛选奇数和偶数示例
2014/04/11 PHP
PHP7内核之Reference详解
2019/03/14 PHP
IE之动态添加DOM节点触发window.resize事件
2010/07/27 Javascript
Javascript事件实例详解
2013/11/06 Javascript
node.js中的fs.write方法使用说明
2014/12/15 Javascript
JavaScript 学习笔记之操作符
2015/01/14 Javascript
如何用angularjs制作一个完整的表格
2016/01/21 Javascript
Vue.js第四天学习笔记
2016/12/02 Javascript
javascript垃圾收集机制的原理分析
2016/12/08 Javascript
jquery中attr、prop、data区别与用法分析
2019/09/25 jQuery
es6 for循环中let和var区别详解
2020/01/12 Javascript
js+css3实现炫酷时钟
2020/08/18 Javascript
TensorFlow实现创建分类器
2018/02/06 Python
wx.CheckBox创建复选框控件并响应鼠标点击事件
2018/04/25 Python
Python列表(list)所有元素的同一操作解析
2019/08/01 Python
python匿名函数lambda原理及实例解析
2020/02/07 Python
Python日志处理模块logging用法解析
2020/05/19 Python
Python rabbitMQ如何实现生产消费者模式
2020/08/24 Python
python wsgiref源码解析
2021/02/06 Python
详解CSS3 rem(设置字体大小) 教程
2017/11/21 HTML / CSS
html5设计原理(推荐收藏)
2014/05/17 HTML / CSS
DJI大疆无人机官方商城:全球领先的无人飞行器研发和生产商
2016/12/21 全球购物
普通大学毕业生自荐信
2013/11/04 职场文书
《长城》教学反思
2014/02/14 职场文书
物流专员岗位职责
2014/02/17 职场文书
党校学习自我鉴定
2014/02/24 职场文书
网页美工求职信范文
2014/04/17 职场文书
优秀员工自荐书
2015/03/06 职场文书
周一问候语大全
2015/11/10 职场文书
2019年图书室自查报告范本
2019/10/12 职场文书
CSS 还能这样玩?奇思妙想渐变的艺术
2021/04/27 HTML / CSS
MySQL中IF()、IFNULL()、NULLIF()、ISNULL()函数的使用详解
2021/06/26 MySQL