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在Windows下安装setuptools(easy_install工具)步骤详解
Jul 01 Python
python使用matplotlib绘制折线图教程
Feb 08 Python
python如何派生内置不可变类型并修改实例化行为
Mar 21 Python
python针对不定分隔符切割提取字符串的方法
Oct 26 Python
用python脚本24小时刷浏览器的访问量方法
Dec 07 Python
python3实现字符串操作的实例代码
Apr 16 Python
用Python实现将一张图片分成9宫格的示例
Jul 05 Python
分享PyCharm的几个使用技巧
Nov 10 Python
Python3 ID3决策树判断申请贷款是否成功的实现代码
May 21 Python
简单了解Django项目应用创建过程
Jul 06 Python
如何用Matlab和Python读取Netcdf文件
Feb 19 Python
pytest进阶教程之fixture函数详解
Mar 29 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
自己动手,丰衣足食 - 短波框形天线制作
2021/03/01 无线电
浅析php插件 HTMLPurifier HTML解析器
2013/07/01 PHP
PHP上传文件时文件过大$_FILES为空的解决方法
2013/11/26 PHP
Linux下从零开始安装配置Nginx服务器+PHP开发环境
2015/12/21 PHP
简单理解PHP的面向对象编程方式
2016/05/17 PHP
PHP读取zip文件的方法示例
2016/11/17 PHP
javascript dom代码应用 简单的相册[firefox only]
2010/06/12 Javascript
JQuery最佳实践之精妙的自定义事件
2010/08/11 Javascript
javascript中的对象创建 实例附注释
2011/02/08 Javascript
JQuery 获取json数据$.getJSON方法的实例代码
2013/08/02 Javascript
解决JS请求服务器gbk文件乱码的问题
2015/10/16 Javascript
使用JQuery中的trim()方法去掉前后空格
2016/09/16 Javascript
微信公众平台开发教程(五)详解自定义菜单
2016/12/02 Javascript
JS实现动画兼容性的transition和transform实例分析
2016/12/13 Javascript
jQuery展示表格点击变色、全选、删除
2017/01/05 Javascript
详解AngularJS脏检查机制及$timeout的妙用
2017/06/19 Javascript
React Native 真机断点调试+跨域资源加载出错问题的解决方法
2018/01/18 Javascript
Vue实现active点击切换方法
2018/03/16 Javascript
Vue中的混入的使用(vue mixins)
2018/06/01 Javascript
Vue之mixin全局的用法详解
2018/08/22 Javascript
jquery拖拽自动排序插件使用方法详解
2020/07/20 jQuery
JavaScript实现五子棋游戏的方法详解
2019/07/08 Javascript
微信小程序基于movable-view实现滑动删除效果
2020/01/08 Javascript
vue动画—通过钩子函数实现半场动画操作
2020/08/09 Javascript
[11:27]《一刀刀一天》之DOTA全时刻20:TI4总奖金突破920W TS赛事分析
2014/06/18 DOTA
Django Highcharts制作图表
2016/08/27 Python
python多任务及返回值的处理方法
2019/01/22 Python
python dict乱码如何解决
2020/06/07 Python
HTML5实现的震撼3D焦点图动画的示例代码
2019/09/26 HTML / CSS
html5 Canvas绘制线条 closePath()实例代码
2012/05/10 HTML / CSS
GLAMGLOW香港官网:明星出镜前的秘密武器
2017/03/16 全球购物
请用Python写一个获取用户输入数字,并根据数字大小输出不同信息的脚本
2014/05/20 面试题
酒店管理专业毕业生推荐信
2013/11/10 职场文书
省级青年文明号申报材料
2014/05/23 职场文书
表扬信格式模板
2015/05/05 职场文书
教你怎么用Python生成九宫格照片
2021/05/20 Python