- 之前讲解的爬取方式都是爬完一个网页接着再爬下一个网页,如果爬取量非常大,则需要等待较长时间。那么有没有办法同时爬取多个网页以提高效率呢?答案是肯定的。本章就来讲解如果通过多线程和多进程同时爬取多个网页,以提高爬取速度。
- 在进行多线程和多进程爬虫编程实战之前,首先来学习线程和进程的概念,以及多线程和多进程提高爬虫效率的原理,建议读者结合7.2节和7.3节的编程实战来理解。已经掌握这部分内容或对原理不感兴趣的读者可以直接阅读编程实战。
7.1.1 计算机硬件结构基础知识
- 学习计算机的硬件结构基础知识有助于我们更好地理解线程和进程的相关概念。
1.计算机主要部件的功能
- 下图为一个实体计算机的主机结构中的主要部件。
- 主板:连接所有其他部件的部件,为CPU、内存、显卡、硬盘等提供平台,相当于人体的躯干,连接着各个器官。
- CPU(Central Processing Unit):中央处理单元,是计算机的运算控制中心。人靠大脑思考,计算机靠CPU来运算和控制,协调各个部件顺利工作。
- 内存:负责硬盘等部件与CPU之间的数据交换。此外,还可以缓存系统中的临时数据。内存中的数据会因断电而消失,内存的大小会影响计算机的运行速度。
- 硬盘:存储资料和软件等数据的部件,有容量大、断电后数据不会丢失的特点。有时也把硬盘成为磁盘,我们常说的C盘、D盘、E盘是指硬盘上的逻辑分区。
- 显卡:负责在显示器上显示一切信息。显卡性能越好,计算机的图形处理能力就越强。
2.CPU、内存、硬盘三者之间的关系
- 下面通过该例子来理解CPU、内存、硬盘三者之间的关系。
- 先举一个计算机上的例子。在计算机上打开QQ时,其实是通过鼠标(输入设备)向CPU发送了一条命令。CPU接收这条命令后,就将QQ程序从硬盘加载到内存中,加载完毕后,CPU开始执行QQ程序。程序启动后,CPU可以让QQ程序显示在显示器上,也就是我们看到的QQ软件界面。如果此时用QQ截取了一张图片,那么这张图片会首先保存在内存中,在没有退出截屏状态时,可以在这张图片上写字、画线条,当另存这张图片时,这张图片就会被保存到硬盘中。
- 再举一个例子。如果把CPU比喻成加工车间,把硬盘比喻成一个大仓库,那么内存就是临时的小仓库。从“距离”上来说,CPU离硬盘远,离内存近。
7.1.2 线程与进程
- 初步理解了CPU、内存、硬盘三者之间的关系后,接下来学习什么是线程和进程。简单来说,CPU是进程的父级单位,一个CPU可以控制多个进程;进程是线程的父级单位,一个进程可以可以控制多个线程。那么到底什么是进程,什么是线程呢?
1.线程和进程的概念
- 对于操作系统来首,一个认为就是一个进程(process),例如:打开一个浏览器就启动了一个浏览器进程;打开一个QQ就启动了一个QQ进程;打开一个Word就启动了一个Word进程,打开两个Word就启动了两个进程。
- 在一个进程内部往往同时做几件事,例如,在浏览器中可以同时浏览网页、听音乐、看视频、下载文件等。在一个进程内部通知书执行的多个“子任务”便称为线程(thread),线程是程序工作的最小单元。
- 单个CPU在某一个时点只能执行一个任务(进程),然而我们在实际操作计算机时可以同时执行多个任务(进程),如一边用浏览器听歌,一边用QQ和好友聊天,这又是如何实现的嗯?
- 答案是操作系统会通过调度算法,轮流各个任务(进程)交替进行。以时间片轮转调度算法为例:假设有5个正在运行的程序(即5个进程)——QQ、微信、谷歌浏览器、网易云音乐、腾讯会议,操作系统会让CPU轮流运行这些进程,一个进程每次运行0.1ms,因为CPU的执行速度非常快,所以看起来就像多个线程同时运行。同理,对于多个线程,例如,在谷歌浏览器(进程)中同时访问网页(线程1)、听在线音乐(线程2)和下载文件(线程3),也是通过类似的时间片轮转调度使得各个子任务(线程)近似于同时执行。
- 虽然单个CPU可以可以通过调度算法“近似同时”执行多个任务,但是如果想真正地并执行多个任务(同时执行多个任务),还是得在多核CPU上实现。现实中由于任务数量远大于CPU数量,就算CPU是多核的,操作系统也会把很多任务轮流调度到每个核心上执行。
- 现在计算机中的CPU基本上都能处理多线程,而且多核CPU已经普及。如下图所示就是一个四核CPU,每个进程可以处理多个线程。
2.线程和进程在爬虫中的应用
- 通过Python执行一个爬虫任务,如“启动爬虫——等待效应——接收源代码”这一系列操作就可以看成是一个线程。如果有多个爬虫任务,在一个线程里只能依次执行,如下图所示。
- 可以看到这样效率是很低的,因为在等待响应的过程中CPU处于闲置状态。合理的安排应该是启动另一个爬虫任务,而不是让程序在那里呆呆地等待。对于这种效率低下的情况,通常有两种解决方案:
- 方案1:在一个进程中启动多个线程,通过多个线程执行多个爬虫任务。
- 方案2:启动多个进程,通过多个进程执行多个爬虫任务。
- 下面就来重点讲解多线程和多进程的相关定义和注意事项。
7.1.3 单线程、多线程与多进程
- 初步理解了线程和进程的基本含义后,可以通过下图快速理解常规CPU操作和IO操作下的单线程(串行)、多线程(并发)与多进程(并行)。总结来说:对于常规CPU操作和IO操作,多线程和多进程都能提高代码运行的效率。
1.单线程
- 单线程又称为串行操作。如上图所示,对于常规单线程操作而言,必须等待上一个程序执行完毕后才能执行下一个程序。在Python中,程序默认都是以单线程的方式执行。
2.多线程
- 多线程又称为并非操作,指在一个时间段里执行多个任务,通常针对单核CPU而言。虽说单核CPU在一个时间点上只能执行一个认为,但是如果执行任务的过程中有不需要用到CPU的环节,如上图中的IO环节是用不到CPU的,那么就可以在线程1不再使用CPU时不再使用CPU执行线程2,从而提高工作效率。
3.多进程
- 多进程又称为并发操作,指在同一时刻可以执行多个任务,通常针对多核CPU而言。因为一个CPU同一时刻只能执行一个任务,所以真正的多进程往往对应多核CPU。通过多进程可以同时执行多个任务,从而提高工作效率。
7.1.4 爬虫任务中的多线程与多进程
- 爬虫任务设计的CPU操作和IO操作如下表所示。
- 从上表可以看出,爬虫涉及的操作大部分都是IO操作,其主要耗时用在等待网络响应以及网络数据交换。因此,在爬虫任务中使用多线程和多进程都能提高效率,如下图所示。
|