多线程爬取海贼王漫画

在上一篇 爬取腾讯动漫海贼王 中,用了大概3小时使用selenium爬取了2万条图片URL。那么有什么好方法能缩短时间呢?下面通过python的多线程改写之前的程序使得完成时间大大缩短。

前置知识:阅读 爬取腾讯动漫海贼王

python版本:python3.7.1

主要使用的python模块: 1.threading 2.queue 3. selenium 4. re

本文参考了Effective Python 中的第37条

可以通过 我的github主页 获取源码 或和我讨论交流

python多线程

首先需要明确由于python的GIL(global interpreter lock 全局解释器锁)的限制,python标准的Thread类的多线程在同一时刻实际上只能有一个线程在执行。

因此如果想用python的多线程进行平行计算,结果会令人失望。

但是若果处理的是阻塞式的I/O操作,会很好的加快程序的执行速度。

读写文件、在网络间通信、以及与显示器等设备交互都属于阻塞时I/O操作。在等待响应的时候,我们可以借助多线程执行其他操作。

代码分析

上一篇文章爬取海贼王漫画的代码是使用selenium模拟浏览器打开网页,并依次点击每张图片,再执行time.sleep(0.3)时等待0.3秒来加载图片。这0.3秒就是等待响应的时间 ,下面分析下列循环

下图中第一个流程图是单进程时的程序流程图

可以看到在执行 time.sleep(0.3)时,白白浪费了CPU资源

下图中的第二个流程图是在多线程的条件下执行。多个线程并发(concurrency)执行。在一个线程等待0.3秒时,阻塞该线程,系统调用另一线程执行。很好的利用了CPU。python线程在执行系统调用的时候会释放GIL,并且一直等到执行完毕才会重新获取它,所以GIL是不会影响系统调用的。

img

代码改写

首先使用python的threading模块中的Thread类和queue模块中的Queue类,Queue类实现了安全的数据交换和锁机制,可以确保线程正常的获取队列中的数据。

所以一个很简单的思路就是将1至693入队,然后线程每次从队列中获取一个数字,组成海贼王漫画每一话的URL,只需稍微修改下原先单进程版本的代码,便可完成。下述代码推荐使用selenium的无界面模式,这样CPU占用会低很多。selenium的有界面模式在线程数较多时,CPU占用过高.

效率分析

在限定网速为1632KB/s时,测试不同线程数量的程序爬取前海贼王前100话URL的时间如下表(selenium都为无界面模式),在5-线程时任务管理器显示CPU已经占100%

类型时间
单进程823秒
2-线程423秒
3-线程315秒
4-线程255秒
5-线程235秒

可以明显看到爬取的速度大大提高了,对于这种阻塞式的I/O操作占用大量时间的程序中,多线程是提高程序速度的一个很好的手段。

编辑于2018-12-09 21:31:41

浙ICP备18050335号