Chapter16 | 爬虫性能提升

  • 一、基础简介
    • 1、任务调度
    • 2、线程与进程
      • 2.1、进程
      • 2.2、线程
      • 2.3、线程与进程的联系
      • 2.4、线程与进程的区别
    • 3、多线程
      • 3.1、多线程的原理
      • 3.2、多线程爬虫结构
      • 3.3、多线程的优势
      • 3.4、与单线程相比
    • 3、Python的多线程模块
      • 3.1、threading模块
      • 3.2、Thread类的调用
      • 3.3、线程池的创建

一、基础简介

1、任务调度

操作系统通常采用时间片轮转的抢占式调度方式
一个任务执行一段时间后强制暂停,去执行下一个任务
每个任务轮流执行

2、线程与进程

2.1、进程

具有独立功能的程序在数据集合上的一次动态执行过程
系统进行资源分配和调度的一个独立单位
任务调度的最小单位
以资源管理器为例

2.2、线程

线程是CPU调度和分派的基本单位
能独立运行
基本上不拥有系统资源,可与通一个进程的其他线程共享进程的资源
一个进程中可以有多个线程

线程与进程的关系

2.3、线程与进程的联系

线程被称为轻量级进程,和进程一样拥有独立的执行控制
一个进程包含多个线程,线程是进程对的一个实体
一个线程可以创建和撤销所属进程中的另一个线程
同一个进程中的多个线程之间可以并发执行

2.4、线程与进程的区别

线程不像进程一样拥有独立的内存空间
线程和所属进程的其他线程共享内存空间
线程之间的通讯更加简单

3、多线程

目前为止,开发的爬虫都属于单线程,不能充分利用硬件资源和带宽资源
多线程是一种常用的提高效率的手段,可以提升网络爬虫性能
Python语言中的threading库提供易用的对线程API

3.1、多线程的原理

在同一进程中,程序的执行在不同线程之间切换
每一时刻,CPU只处理一个线程
CPU在不同线程之间快速切换,给人一种同时处理多个线程的错觉
一个线程等待网页下载时,进程可以切换到其他线程执行任务,避免浪费CPU资源

3.2、多线程爬虫结构


使用多线程爬虫结构可以提高爬虫的效率。

3.3、多线程的优势

多线程的目的是更大限度的利用CPU资源
当某一线程的处理不需要占用CPU,只和I/O等资源打交道时,其他线程有机需要获得CPU资源
对于计算密集型的应用,CPU间歇,同时其他可运行的资源较少。此时,CPU不能“腾出手来”处理其他线程

3.4、与单线程相比

对爬取1000个网页的效果进行对比

举例:

豆瓣电影使用单线程

%%time
import requests
import rebase_url = 'https://movie.douban.com/tag/喜剧'
params = {'start':'0','type':'T','timeout':'5'}
html = requests.get(base_url,params=params).text
r = re.compile('<a calss="nbg" .* title=\"?(.*)\"')
print(','.join(r.findall(html)))

3、Python的多线程模块

Python提供多个模块来支持多线程编程

thread:提供基本的线程和锁定支持
threading:提供更高级别的、功能更全的线程管理
Queue:创建队列数据结构、用于多线程之间进行共享

  • 选用threading模块来实现多线程
  • 相较于thread模块

threading包含thread模块的大部分功能
threading包括许多非常好用的同步机制

3.1、threading模块

Thread类:threading模块的主要执行对象

使用Thread类创建线程

创建Thread的实例,传入一个函数
创建Thread的实例,传入一个可调用的类实例
派生Thread的子类,并创建子类的实例

%%time
import requests
import threading
import rebase_url = 'https://movie.douban.com/tag'
r =re.compile('<a calss="nbg" .* title=\"?(.*)\"')
def worker(tag):url = base_url +tagparams = {'start':'0','type':'T','timeout':'5'}html = requests.get(base_url,params=params).textthread_name = threading.currentThread().getName()print(thread_name,','.join(r.findall(html)),'\n')
threads = []
for tag in ['喜剧','动画','剧情']:thread = threading.Thread(name='Thread-' + tag,target=worker,args=(tag,))threads.append(thread)thread.start()
for thread in threads:thread.join()

串行的爬取策略如下

%%time
import requests
import threading
import rebase_url = 'https://movie.douban.com/tag/'
r =re.compile('&lt;a class="nbg" .* title=\"?(.*)\"')
def worker(tag):url = base_url +tagparams = {'start':'0','type':'T','timeout':'5'}html = requests.get(base_url,params=params).text
for tag in ['喜剧','动画','剧情']:worker(tag)

3.2、Thread类的调用

创建函数的部分为:
thread = threading.Thread(name='Thread-' + tag,target=worker,args=(tag,))

Thread的构造函数包含以下参数

name:定义线程的名字
target:指定线程启动时要执行的函数
args:线程启动时传递给target函数的参数

线程创建之后,调用join方法,然后等待线程结束
thread.join()
join方法会一直阻塞,直到thread线程结束

下面代码中的worker函数,其实就是每一个线程thread中的target,即需要执行的函数

def worker(tag):url = base_url +tagparams = {'start':'0','type':'T','timeout':'5'}html = requests.get(base_url,headers=headers,params=params).textthread_name = threading.currentThread().getName()print(thread_name,','.join(r.findall(html)),'\n')

worker函数完成对特定标签下的电影名称的抓取

3.3、线程池的创建

如果每一个任务都需要创建一个新线程。
那么线程的创建和销毁都比较消耗资源,这时候需要创建线程池来解决问题。

from queue import Queue
import inspect
import threading
import re
import timeclass ThreadPool(object):def __init__(self,thread_num,worker,queue):assert isinstance(thread_num,int)assert inspect.isfunction(worker)# assert isinstance(queue,Queue)self.queue = queueself.threads = []self.stop_event = threading.Event()for i in range(0,thread_num):thread = threading.Thread(name='Thread-'+ str(i),target=worker,args=(self,queue,self.stop_event, ))self.threads.append(thread)for thread in self.threads:thread.start()def join(self,wait_until_all_task_done=True):# 等到所有任务完成if wait_until_all_task_done:self.queue.join()# 设置线程结束self.stop_event.set()for thread in self.threads:thread.join()def worker(queue,stop_event):thread_name = threading.currentThread().getName()while not stop_event.is_set():try:task_id = queue.get(timeout = 1)  # 阻塞1秒,防止永久阻塞print(thread_name,task_id)queue.task_done()except Exception as e :print(e)queue = Queue()
pool = ThreadPool(2,worker,queue)
for tag in range(1,5):queue.put(tag)
pool.join()

快速入门网络爬虫系列 Chapter16 | 爬虫性能提升相关推荐

  1. 零基础编程入门python视频-Python编程零基础小白快速入门完整全系列精品课

    1. 课程咨询加老师助理微信:助理1微信: chenjinglei88 ,助理2微信: omf6757 2. 决定购买并想得到陈敬雷老师亲自指导(课程或自己项目难题均可)加老师微信: chenjing ...

  2. 【python爬虫系列】爬虫+Selenium

    文章目录 Python下Selenium安装及环境配置 Python Selenium库的使用 基础知识 Selenium 快速入门 python爬取百度 python爬取拉勾招聘 selenium. ...

  3. Java爬虫系列(五) - 爬虫补充内容+ElasticSearch展示数据

    Java爬虫内容补充和ElasticSearch 网页去重 之前我们对下载的url地址进行了去重操作,避免同样的url下载多次.其实不光url需要去重,我们对下载的内容也需要去重. 在网上我们可以找到 ...

  4. RTKLIB 开源代码之科普快速入门网络资料产品/数据下载

    对于新手而言,RTKLIB本身的功能完全能够满足你们的需求:而且最好的参考资料就是RTKLIB MANUAL,介绍的很全,很细,包括怎么使用,每个模块的功能甚至对于代码所用的模型都有介绍:但是对于英文 ...

  5. 如何快速入门网络基础知识(TCP/IP 和 HTTP)

    前言 在写之前,先给这篇文章做一个明确定位,读完这篇文章后,希望你能够: 对于计算机网络有初步的认识和了解,了解一些经典专业术语,如三次握手.四次挥手.DNS解析的含义. 了解一些应用层协议,如传统的 ...

  6. 锐龙4000系列运行matlab,性能提升60%!AMD锐龙运行Matlab恢复正常

    Matlab是美国MathWorks出品的商业数学软件,用于算法开发.数据可视化.数据分析以及数值计算等用途.在2020a版本中,Matlab正式修复了之前在AMD锐龙平台上存在的性能问题,使用Ryz ...

  7. 爬虫系列:穿越网页表单与登录窗口进行采集

    上一期我们讲解了数据标准化相关内容,首先对单词出现的频率进行排序,之后对一些大小写进行转换,缩小 2-gram 序列的重复内容. 当我们真正迈出网络数据采集基础之门的时候,遇到的第一个问题可能是:&q ...

  8. 【完结】12大深度学习开源框架(caffe,tf,pytorch,mxnet等)快速入门项目

    这是一篇总结文,给大家来捋清楚12大深度学习开源框架的快速入门,这是有三AI的GitHub项目,欢迎大家star/fork. https://github.com/longpeng2008/yousa ...

  9. 【完结】给新手的12大深度学习开源框架快速入门项目

    文/编辑 | 言有三 这是一篇总结文,给大家来捋清楚12大深度学习开源框架的快速入门,这是有三AI的GitHub项目,欢迎大家star/fork. https://github.com/longpen ...

最新文章

  1. Waymo高管指责媒体夸大自动驾驶的商业化前景
  2. 《C#高级编程》既不高级,也不基础,东拼西凑的味道十足。。。
  3. 卷积神经网络(cnn)的体系结构
  4. Python4:DataStructure
  5. LINUX下动态链接库的使用-dlopen dlsym dlclose dlerror
  6. 基于python的modbus协议编程_通往未来的网络可编程之路:Netconf协议与YANG Model
  7. 可是笑声太响了的64391111
  8. 【转】simulink中的sample time设置
  9. mysql sleep进程 java_请教java更新mysql,更新进程sleep
  10. Uptime-Kuma 一个轻量的开源监控工具
  11. 用python画雨滴_python实现雨滴下落到地面效果
  12. 全球知名虚拟服务器,国外十大虚拟主机
  13. 百度编辑器ueditor添加视频方法
  14. 最近在 vscode 中借助 gcc 编译器来配置 c
  15. 判断字符串是否包含在某个集合中
  16. IT人员要善用图表来说明问题
  17. MyBatis-Plus 从入门到上手-进阶版
  18. 养生之道--21天改变体质
  19. 通义听悟上线,强大的视频会议和学习直播分析能力,人工智能如何改变我们的生活和工作方式?
  20. 如何解决服务器网络中断而导致程序中断的问题

热门文章

  1. Java(if, else,else if)
  2. 为数不多的真正解决VMware与 Device/Credential Guard 不兼容,关闭了hyper-v还是不行
  3. 「镁客早报」美国初创公司Rocket Lab完成发射一箭六星商业任务;工信部表示:6G概念研究将于今年启动...
  4. mw如何解读_汽轮机CN135MW运行规程解读
  5. 建筑设计用计算机要求高吗,建筑设计电脑怎么选?高配置性能是关键
  6. Unity animiator 学习记录【2D角色移动】
  7. MySQL高级特性一:分区表
  8. 记【友盟+】Outing之旅 | 山西篇 (内附招聘)
  9. PFC 5.00.35中,如何去掉二维球形颗粒的黑色边框?很简单
  10. 【Scipy高级计算】(3) 一维插值方法,附python完整代码