到目前为止,实际上我们的爬虫进程总共介绍了:
爬虫架构——确认目标(爬虫对象)——分析网页(抓包分析,URL咋变的,什么参数?)——请求网页(requests库)——解析网页(bs4,lxml)——提取内容(xpath,css selector,re,find,find_all)——封装内容(转json,转dict)——本地写入(txt,csv,json,html)——入库(mysql)——可视化绘图(pyecharts)的整个简单流程。
而在上一篇说的是,
python3爬虫系列13之find_all爬虫高考分数线并绘制分析图(普通版),
在网页数据爬取以后,发现在数据量不大的时候,这种普通的程序依然速度很慢,那么想要做到 快速爬虫,就需要知道
使用它们,进程、单进程、多进程、线程、单线程、多线程、并行、并发、互斥锁、协程。往往可以 让我们的爬虫程序加速冲刺。
OMG,这么多?要学个三五十年吧?放心了,我只说总结,不啰嗦。(因为我也不看源码。。。)
进程就是正在运行的程序
比如你的电脑系统现在正在运行着的QQ(酷狗,微信啥子随便了。)就是一个进程。
一旦你的「QQ」运行起来,系统就会给「QQ」分配了内存和资源。
进程和进程之间是互相独立的,分配的空间也不交集。
单进程就是你的电脑太破,只允许运行一个程序。其他的运行就炸。
简单来说就是电脑只能做一件事情.比如电脑打开了QQ,就不能再去打开淘宝。
多进程就是你的电脑允许运行多个程序,在同一段时间里面
可以 “同时” 执行多个任务。
简单来说就是电脑可以同一时间在做很多事情,一边玩听歌一边看片。
原理就是你的CPU 在做进程之间的切换,因为CPU 的切换速度超级快,快到让你感觉到,开着的所有程序好像是在同时运行。
这样就提高了 CPU 的使用率了,所有代码后期都爱提及多进程。同理你的爬虫就可以使用多进程。
线程是比进程更小的一个单位,可以说是程序用 CPU 的一个基本单元。它存在于进程之中,而且有很多兄弟伙。
简单来说就是在一个进程里面,可以执行多个任务,在这里的每一个任务就是一个线程。
单线程是一个程序里,如果只是单一的一个执行路径,那么它就是单线程的。就是什么,你是个独生子。
简单来说就是在一个进程里面,要执行多个任务,但是呢,完成任务的方式只有一个单一的执行路径,那么它就是单线程的。
单线程是一个程序里,如果只是单一的一个执行路径,那么它就是单线程的。就是什么,你是个独生子。
简单来说就是在一个进程里面,要执行多个任务,但是呢,完成任务的方式有多个执行路径,那么它就是多线程的。
So:
想要让爬虫更高效,就可以让你的爬虫实现多线程。
既然说到了线程,自然离不开并行和并发。
在某一个【时间段内】,可以同时执行多个进程,这就是并行。
简单来说,一个单核的 CPU每次只能执行一个进程,那么一个多核的 CPU,就可以同时执行多个进程了。这样这些同时运行的多个进程,就是一种并行方式。
在某一个【时间点】,同时执行多个进程,这就是并发。
简单来说就是 在 双十一的时候,晚上的 12 点,大伙的女朋友们都在握着手机,准备同时秒杀某一个商品。这个多人一起抢一个东西,就是一种并行方式。
保安,让线程别他妈乱来,排好队,一个一个线程安全有序的去执行。
在系统里面,进程和进程之间是互相独立的,而我们知道,一个进程里面有多个线程,而线程之间却是共享一个进程空间的。
简单来说,
你想啊,一个蛋糕好多个线程一起分,劳资又不是恐龙,谁都不让,难免就有一些线程就要搞事情了。
于是好多线程都暴动了,这样数据就不安全了,所以就有了互斥锁的出现。
它的作用就是让线程别他妈乱来,排好队,一个一个线程安全有序的去执行。
很多开发语言中都有这个互斥锁的存在。名字可能不一样哟。
有了互斥锁的出现,python中取了个别名叫GIL :全称是 Global Interpreter Lock(全局解释器锁)。
就是用来控制线程执行权限的,线程需要执行的时候,要先获得 GIL 之后才可以执行,这样就不会产生线程安全问题。
这东西设计之初的考虑,为了数据安全所做的决定。某个线程想要执行,必须先拿到 GIL,我们可以把 GIL 看作是“通行证”,并且在一个
Python 进程中,GIL 只有一个。拿不到通行证的线程,就不允许进入 CPU 执行。
so:
在 Python 中,无论是单核还是多核,都同时只能有一个线程在执行。其根源就是因为 GIL 锁的存在。
相比python,其他语言(比如java)CPU 是多核时是支持多个线程同时执行。尴尬了。
上面我们知道了在python中因为 GIL 锁,我们同时只能有一个线程在执行。
这意味着多线程还有个毛用啊?
此时,python提出了另外一个特性:在 I/O 流阻塞的时候,GIL会被释放。(GIL被炒鱿鱼了)
(所谓I/O流就是输入输出流)
就是说以后你写Python 程序:
如果是要处理一些【输入输出的多任务】,在 I/O 流阻塞的时候,GIL会被释放,相对于GIL被炒鱿鱼了,就可以开启多线程。
如果是要处理【多任务】,想要充分的去利用我们多核的CPU,就开启多进程。因为对于频繁的cpu操作,由于GIL锁的原因,多个线程只能用一个cpu,这时多进程的执行效率要比多线程高。
协程也叫微线程。
在一个线程里面可以执行多个函数,线程和进程是通过系统调度的(也就是函数之间由系统来自行调度,开销小)。
而协程(微线程)不需要通过系统调度,可以根据需要自己调度。(因为微线程是函数之间在切换,所以开销更小)。在 python 中使用微线程时一般会用到 (genvent、monkey.patch_all)
python什么时候使用多线程,什么时候使用多进程?
多线程使用场景:IO密集型- 输入输出处理(频繁读取文件,读取网络套接字),大多时间是在等待。io 操作不占用CPU(从硬盘、从网络、从内存读数据都算io,网络并发这一类的。
多进程使用场景:CPU密集型-绝大多数时间在数学与逻辑运算,比如批量爬取很多数字,文本数据,求平均值,数据分析等。
小提示:Python中 time.sleep 是阻塞的,都知道使用它要谨慎,但在多线程编程中,time.sleep 并不会阻塞其他线程。使用os.system(‘pause’)