百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术流 > 正文

一次说明白Python爬虫中多线程,多进程,异步IO编程

citgpt 2024-09-09 02:16 8 浏览 0 评论

图/文:迷神

我们在Python爬虫中,重要的是讲究速度,如果有10万或者100万Url地址,写过爬虫的都会知道,那估计是非常慢的。我们的Python爬虫一般IO密集型业务,Python爬虫程序需要发起网络请求,必然就有网络IO阻塞,通常请求一个URL耗时要几百毫秒到几秒,逐步执行,和我们CPU那么高性能比起来,那真是天壤之别。

一次说明白Python爬虫中多线程,多进程,异步IO编程

比如,我们Python爬虫在单线程同步爬取过程中,一个个的爬取网站所有的URL,假设100个URL,平均每个URL请求的时间是1秒,那么在单线程同步场景下,最快也需要100秒钟,才能把所有的页面爬取下来。

在网页数据爬取以后,发现在数据量不大的时候,这种普通的程序还勉强,如果想极大提高速度,做到 快速爬虫,就需要使用多线程,多进程,异步IO编程了。不过,Python中有一个臭名昭著的GIL,导致做不到真正的并行运算,多核无法真正利用起来。多线程在切换线程,还有切换成本,以及线程的创建成本。如果使用多进程,虽然能利用多核处理的优势,但是多进程的创建本城比线程更高,而IO密集型任务,CPU不是瓶颈。

鉴于此,Python3.4 还是引入了异步 asyncio 模块,增加了异步编程,跟 JavaScript 的async/await 极为类似,大大方便了异步任务的处理。异步编程使得CPU不再需要再去等待耗时的操作,而是让出CPU时间给其他任务执行,可以极大提高完成所有的任务速度。

下面,我们通过具体的小例子,来看看多线程,多进程,异步IO编程的区别:

1、普通同步,单线程阻塞

单线程版本,所有的任务,按照顺序依次等待执行。

结果如下:

可以发现,总共5个任务,他们每个任务执行时间是1秒钟,单进程阻塞时,总共耗时是5秒多一点点。

2、多线程版本任务

简单来说就是在一个进程里面,可以执行多个任务,在这里的每一个任务就是一个线程。

执行结果:

换成多线程之后,5个线程各负责一个任务。我们看到执行结果:1.0039010047912598 已经明显比第一个快很多了。即使有GIL

多进程版本任务

多进程就是你的电脑允许运行多个程序,在同一段时间里面,可以 “同时” 执行多个任务。

执行结果:

执行结果:1.7484214305877686。是不是很奇怪,使用多进程,时间比多线程更慢,为什么?因为创建进程的成本是要比线程高的,虽然,它可以利用多核CPU的优势。

异步版本多个任务

最后,我们来看看异步模式下,怎么样。

执行结果:

发现使用asyncio所花的时间是最少的。asyncio可以实现单线程并发IO操作,它没有多线程和进程的创建成本,就是在单线程环境下,切换任务,当这个任务被阻塞时,立刻切换其他任务,当前面的任务完成时,在通知它,这样效率就极大的提高了。

最后,值得一说的就是一个不错的HTTP框架:aiohttp,它是一个基于asyncio实现的非常强大的HTTP框架,很值得学习哦。

相关推荐

js中arguments详解

一、简介了解arguments这个对象之前先来认识一下javascript的一些功能:其实Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数...

firewall-cmd 常用命令

目录firewalldzone说明firewallzone内容说明firewall-cmd常用参数firewall-cmd常用命令常用命令 回到顶部firewalldzone...

epel-release 是什么

EPEL-release(ExtraPackagesforEnterpriseLinux)是一个软件仓库,它为企业级Linux发行版(如CentOS、RHEL等)提供额外的软件包。以下是关于E...

FullGC详解  什么是 JVM 的 GC
FullGC详解 什么是 JVM 的 GC

前言:背景:一、什么是JVM的GC?JVM(JavaVirtualMachine)。JVM是Java程序的虚拟机,是一种实现Java语言的解...

2024-10-26 08:50 citgpt

使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
跨域(CrossOrigin)

1.介绍  1)跨域问题:跨域问题是在网络中,当一个网络的运行脚本(通常时JavaScript)试图访问另一个网络的资源时,如果这两个网络的端口、协议和域名不一致时就会出现跨域问题。    通俗讲...

微服务架构和分布式架构的区别

1、含义不同微服务架构:微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并...

深入理解与应用CSS clip-path 属性
深入理解与应用CSS clip-path 属性

clip-pathclip-path是什么clip-path 是一个CSS属性,允许开发者创建一个剪切区域,从而决定元素的哪些部分可见,哪些部分会被隐...

2024-10-25 11:51 citgpt

HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
Request.ServerVariables 大全

Request.ServerVariables("Url")返回服务器地址Request.ServerVariables("Path_Info")客户端提供的路...

python操作Kafka

目录一、python操作kafka1.python使用kafka生产者2.python使用kafka消费者3.使用docker中的kafka二、python操作kafka细...

Runtime.getRuntime().exec详解

Runtime.getRuntime().exec详解概述Runtime.getRuntime().exec用于调用外部可执行程序或系统命令,并重定向外部程序的标准输入、标准输出和标准错误到缓冲池。...

promise.all详解 promise.all是干什么的
promise.all详解 promise.all是干什么的

promise.all详解promise.all中所有的请求成功了,走.then(),在.then()中能得到一个数组,数组中是每个请求resolve抛出的结果...

2024-10-24 16:21 citgpt

Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解

取消回复欢迎 发表评论: