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 collections模块实例讲解
Apr 07 Python
在Python的Django框架中使用通用视图的方法
Jul 21 Python
Python3.2模拟实现webqq登录
Feb 15 Python
分享vim python缩进等一些配置
Jul 02 Python
Python3实现mysql连接和数据框的形成(实例代码)
Jan 17 Python
python实现滑雪者小游戏
Feb 22 Python
python中resample函数实现重采样和降采样代码
Feb 25 Python
TensorFlow使用Graph的基本操作的实现
Apr 22 Python
python3环境搭建过程(利用Anaconda+pycharm)完整版
Aug 19 Python
解决Ubuntu18中的pycharm不能调用tensorflow-gpu的问题
Sep 17 Python
python 基于opencv操作摄像头
Dec 24 Python
python 如何读、写、解析CSV文件
Mar 03 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
Yii中CGridView禁止列排序的设置方法
2016/07/12 PHP
PHP之十六个魔术方法详细介绍
2016/11/01 PHP
laravel5.2实现区分前后台用户登录的方法
2017/01/11 PHP
28个JS验证函数收集
2010/03/02 Javascript
深入理解javaScript中的事件驱动
2013/05/21 Javascript
JavaScript通过function定义对象并给对象添加toString()方法实例分析
2015/03/23 Javascript
Bootstrap模仿起筷首页效果
2016/05/09 Javascript
JS身份证信息验证正则表达式
2017/06/12 Javascript
js将当前时间格式化为 年-月-日 时:分:秒的实现代码
2018/01/20 Javascript
浅谈使用mpvue开发小程序需要注意和了解的知识点
2018/05/23 Javascript
详解vscode中vue代码颜色插件
2018/10/11 Javascript
JavaScript从原型到原型链深入理解
2019/06/03 Javascript
Python中获取网页状态码的两个方法
2014/11/03 Python
Python中AND、OR的一个使用小技巧
2015/02/18 Python
python探索之BaseHTTPServer-实现Web服务器介绍
2017/10/28 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
2017/12/20 Python
Python实现的NN神经网络算法完整示例
2018/06/19 Python
对Python3.6 IDLE常用快捷键介绍
2018/07/16 Python
Python爬虫基础之XPath语法与lxml库的用法详解
2018/09/13 Python
给我一面国旗 python帮你实现
2019/09/30 Python
如何使用python切换hosts文件
2020/04/29 Python
使用Pytorch搭建模型的步骤
2020/11/16 Python
基于python+selenium自动健康打卡的实现代码
2021/01/13 Python
HTML5 Web 存储详解
2016/09/16 HTML / CSS
联想墨西哥官方网站:Lenovo墨西哥
2016/08/17 全球购物
线程的基本概念、线程的基本状态以及状态之间的关系
2012/10/26 面试题
JavaScript实现前端网页版倒计时
2021/03/24 Javascript
通信专业个人自我鉴定
2013/10/21 职场文书
学习委员自我鉴定
2014/01/13 职场文书
企业后勤岗位职责
2014/02/28 职场文书
材料工程专业毕业生求职信
2014/03/04 职场文书
美容院营销方案
2014/03/05 职场文书
百年校庆感言
2015/08/01 职场文书
react国际化react-intl的使用
2021/05/06 Javascript
SQL注入的实现以及防范示例详解
2021/06/02 MySQL
Linux系统下安装PHP7.3版本
2021/06/26 PHP