[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程

图/文:迷神
我们在Python爬虫中 , 重要的是讲究速度 , 如果有10万或者100万Url地址 , 写过爬虫的都会知道 , 那估计是非常慢的 。 我们的Python爬虫一般IO密集型业务 , Python爬虫程序需要发起网络请求 , 必然就有网络IO阻塞 , 通常请求一个URL耗时要几百毫秒到几秒 , 逐步执行 , 和我们CPU那么高性能比起来 , 那真是天壤之别 。
比如 , 我们Python爬虫在单线程同步爬取过程中 , 一个个的爬取网站所有的URL , 假设100个URL , 平均每个URL请求的时间是1秒 , 那么在单线程同步场景下 , 最快也需要100秒钟 , 才能把所有的页面爬取下来 。
在网页数据爬取以后 , 发现在数据量不大的时候 , 这种普通的程序还勉强 , 如果想极大提高速度 , 做到快速爬虫 , 就需要使用多线程 , 多进程 , 异步IO编程了 。 不过 , Python中有一个臭名昭著的GIL , 导致做不到真正的并行运算 , 多核无法真正利用起来 。 多线程在切换线程 , 还有切换成本 , 以及线程的创建成本 。 如果使用多进程 , 虽然能利用多核处理的优势 , 但是多进程的创建本城比线程更高 , 而IO密集型任务 , CPU不是瓶颈 。
鉴于此 , Python3.4还是引入了异步asyncio模块 , 增加了异步编程 , 跟JavaScript的async/await极为类似 , 大大方便了异步任务的处理 。 异步编程使得CPU不再需要再去等待耗时的操作 , 而是让出CPU时间给其他任务执行 , 可以极大提高完成所有的任务速度 。
下面 , 我们通过具体的小例子 , 来看看多线程 , 多进程 , 异步IO编程的区别:1、普通同步 , 单线程阻塞
单线程版本 , 所有的任务 , 按照顺序依次等待执行 。
[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程
文章图片
单线程
结果如下:
[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程
文章图片
结果
可以发现 , 总共5个任务 , 他们每个任务执行时间是1秒钟 , 单进程阻塞时 , 总共耗时是5秒多一点点 。 2、多线程版本任务
简单来说就是在一个进程里面 , 可以执行多个任务 , 在这里的每一个任务就是一个线程 。
[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程
文章图片
多线程任务
执行结果:
[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程
文章图片
执行结果
换成多线程之后 , 5个线程各负责一个任务 。 我们看到执行结果:1.0039010047912598已经明显比第一个快很多了 。 即使有GIL多进程版本任务
多进程就是你的电脑允许运行多个程序 , 在同一段时间里面 , 可以“同时”执行多个任务 。
[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程
文章图片
多进程版本
执行结果:
[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程
文章图片
直接结果
执行结果:1.7484214305877686 。 是不是很奇怪 , 使用多进程 , 时间比多线程更慢 , 为什么?因为创建进程的成本是要比线程高的 , 虽然 , 它可以利用多核CPU的优势 。 异步版本多个任务
最后 , 我们来看看异步模式下 , 怎么样 。
[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程
文章图片
异步
执行结果:
[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程
文章图片
执行结果
发现使用asyncio所花的时间是最少的 。 asyncio可以实现单线程并发IO操作 , 它没有多线程和进程的创建成本 , 就是在单线程环境下 , 切换任务 , 当这个任务被阻塞时 , 立刻切换其他任务 , 当前面的任务完成时 , 在通知它 , 这样效率就极大的提高了 。
【[迷神笔记]多进程,异步IO编程,一次说明白Python爬虫中多线程】最后 , 值得一说的就是一个不错的HTTP框架:aiohttp , 它是一个基于asyncio实现的非常强大的HTTP框架 , 很值得学习哦 。