python线程池并发爬虫_python爬虫14 & 如果你不懂多线程和线程池,那就去河边摸鱼...

你知道吗?

在我的心里

你是多么的重要

就像

请允许我来一段 freestyle

你们准备好了妹油

你看

这个碗

e22ef8deg00qd0qhe000ec0004f0046c.gif

它又大又圆

就像

这条面

?url=http%3A%2F%2Fdingyue.ws.126.net%2F2020%2F0706%2F519d6325j00qd0qhe000ac0007t008cc.jpg&thumbnail=650x2147483647&quality=80&type=jpg

它又长又宽

你们

在这里

看文章

觉得 很开心

就像

我在这里

给你们

写文章

觉得很开心

skr~~

?url=http%3A%2F%2Fdingyue.ws.126.net%2F2020%2F0706%2Fb1c6ce21j00qd0qhe000mc000c800c2c.jpg&thumbnail=650x2147483647&quality=80&type=jpg

不好意思

走错片场了

ok..

接下来,就是

学习 python 的正确姿势

d99eb063g00qd0qhe000sc0008c008cc.gif

咱们在上一次的

python爬虫13 | 秒爬,多线程爬取速度也太猛了,爬虫效率杠杠的

了解了一些 python 高效爬虫的概念

比如多线程、多进程、协程等

那么我们这一篇就开始了解多线程的具体使用

在 python 中

常用的多线程的模块有这么几个

_thread

threading

Queue

之前有个 thread 模块

被 python3 抛弃了

改名为 _thread

但其实 _thread 也没什么人用

因为 _thread 有的 threading 都有

_thread 没有的 threading 依然有

?url=http%3A%2F%2Fdingyue.ws.126.net%2F2020%2F0706%2F4d5f7624j00qd0qhe0008c0007e006bc.jpg&thumbnail=650x2147483647&quality=80&type=jpg

那么接下来我们就先来玩玩 threading 吧

在此之前

(请允许小帅b又开始吹水了~)

介绍一下 小帅b 的一点背景

小帅b呢

平常上班时间都会去河边摸鱼

每天得摸 20 条鱼

2a6f9e3eg00qd0qhe0015c0002s002sc.gif

一条一条的摸

为的是什么

为的是安抚这些鱼的心情

这样以后送到餐前的红烧鱼才更加美味

?url=http%3A%2F%2Fdingyue.ws.126.net%2F2020%2F0706%2F889becf5j00qd0qhe0009c0007i004nc.jpg&thumbnail=650x2147483647&quality=80&type=jpg

小帅b每天得摸 20 条鱼

每隔一秒钟摸一条

也就是这样

import timedef moyu_time(name, delay, counter): while counter: time.sleep(delay) print("%s 开始摸鱼 %s" % (name, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))) counter -= 1if __name__ == '__main__': moyu_time('小帅b',1,20)

后来

小帅b知道了多线程

拍脑一想

我靠

应该把小明和小红拉过来

让他们一起帮我摸鱼啊

也就是让小明和小红同时一人摸 10 条鱼

想想就开心

?url=http%3A%2F%2Fdingyue.ws.126.net%2F2020%2F0706%2F26ec3069j00qd0qhe0005c0004s005ic.jpg&thumbnail=650x2147483647&quality=80&type=jpg

在 小帅b 的威逼利诱下

他们俩不情愿的手拉着手来到了河边

小帅b看小红是女生

就让小红每摸一条鱼休息 2 秒钟

而小明每摸一条鱼休息 1 秒钟

先扔一段代码给你

# encoding = utf-8import threadingimport time# 创建一个线程子类class MyThread(threading.Thread): def __init__(self,threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print("开始线程:" + self.name) moyu_time(self.name, self.counter, 10) print("退出线程:" + self.name)def moyu_time(threadName, delay, counter): while counter: time.sleep(delay) print("%s 开始摸鱼 %s" % (threadName, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))) counter -= 1# 创建新线程# 小帅b找了两个人来摸鱼# 让小明摸一次鱼休息1秒钟# 让小红摸一次鱼休息2秒钟thread1 = MyThread(1, "小明", 1)thread2 = MyThread(2, "小红", 2)# 开启新线程thread1.start()thread2.start()# 等待至线程中止thread1.join()thread2.join()print ("退出主线程")

在这里呢

我们创建了一个线程类

然后继承 threading.Thread

在我们这个线程类里面定义了一个 run 方法

这个 run 方法去调用了摸鱼的方法

可以看到我们创建了两个线程

一个叫小明线程

一个叫小红线程

thread1 = MyThread(1, "小明", 1)thread2 = MyThread(2, "小红", 2)

当我们的线程调用 start 方法的时候

它们就会去执行 run 方法

而我们用到的 join 方法呢

是为了让线程执行完

再终止主程序

运行一下就是这样

开始线程:小明开始线程:小红小明 开始摸鱼 2019-03-10 23:15:26小红 开始摸鱼 2019-03-10 23:15:27小明 开始摸鱼 2019-03-10 23:15:27小明 开始摸鱼 2019-03-10 23:15:28小红 开始摸鱼 2019-03-10 23:15:29小明 开始摸鱼 2019-03-10 23:15:29小明 开始摸鱼 2019-03-10 23:15:30小明 开始摸鱼 2019-03-10 23:15:31小红 开始摸鱼 2019-03-10 23:15:31小明 开始摸鱼 2019-03-10 23:15:32小明 开始摸鱼 2019-03-10 23:15:33小红 开始摸鱼 2019-03-10 23:15:33小明 开始摸鱼 2019-03-10 23:15:34小红 开始摸鱼 2019-03-10 23:15:35小明 开始摸鱼 2019-03-10 23:15:35退出线程:小明小红 开始摸鱼 2019-03-10 23:15:37小红 开始摸鱼 2019-03-10 23:15:39小红 开始摸鱼 2019-03-10 23:15:41小红 开始摸鱼 2019-03-10 23:15:43小红 开始摸鱼 2019-03-10 23:15:45退出线程:小红退出主线程Process finished with exit code 0

小帅b再也不用摸鱼了

后来小明和小红都不乐意了

凭什么就我们两个摸鱼

?url=http%3A%2F%2Fdingyue.ws.126.net%2F2020%2F0706%2F1f18555aj00qd0qhe0005c0005k005kc.jpg&thumbnail=650x2147483647&quality=80&type=jpg

这时候 小帅b 只能去找更多人了

连 小帅b 家的狗都叫过来了

然后

就疯狂的开启线程

thread1 = MyThread(1, "小明", 1)thread2 = MyThread(2, "小红", 2)thread3 = MyThread(3, "小黄", 2)thread4 = MyThread(4, "小绿", 2)...thread5 = MyThread(55, "小青", 2)thread6 = MyThread(56, "小白", 2)thread7 = MyThread(57, "小狗", 2)

stop!!!

?url=http%3A%2F%2Fdingyue.ws.126.net%2F2020%2F0706%2F317ab396j00qd0qhe0005c0005i004ec.jpg&thumbnail=650x2147483647&quality=80&type=jpg

这可不行

因为频繁的创建线程 销毁线程

非常的浪费资源

所以呢

应该把他们放到池子里面去一起洗澡

14addce4g00qd0qhe000nc0003r002sc.gif

哈,也就是

线程池

通过线程池就可以重复利用线程

不会造成过多的浪费

在 python 中

可以使用 ThreadPoolExecutor 来实现线程池

我们来往池子里塞 20 个线程

然后在循环的时候每次拿一个线程来摸鱼

def moyu_time(name, delay, counter): while counter: time.sleep(delay) print("%s 开始摸鱼 %s" % (name, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))) counter -= 1if __name__ == '__main__': pool = ThreadPoolExecutor(20) for i in range(1,5): pool.submit(moyu_time('xiaoshuaib'+str(i),1,3))

运行一下

xiaoshuaib1 开始摸鱼 2019-03-10 23:30:10xiaoshuaib1 开始摸鱼 2019-03-10 23:30:11xiaoshuaib1 开始摸鱼 2019-03-10 23:30:12xiaoshuaib2 开始摸鱼 2019-03-10 23:30:13xiaoshuaib2 开始摸鱼 2019-03-10 23:30:14xiaoshuaib2 开始摸鱼 2019-03-10 23:30:15xiaoshuaib3 开始摸鱼 2019-03-10 23:30:16xiaoshuaib3 开始摸鱼 2019-03-10 23:30:17xiaoshuaib3 开始摸鱼 2019-03-10 23:30:18xiaoshuaib4 开始摸鱼 2019-03-10 23:30:19xiaoshuaib4 开始摸鱼 2019-03-10 23:30:20xiaoshuaib4 开始摸鱼 2019-03-10 23:30:21

可以看到

我们每次从线程池里面去拿一个线程来摸鱼

这样就不会去重复的创建销毁线程了

当然

我们还可以用一个叫做 Queue 的队列来创建线程池

队列嘛~

就是可以往里塞东西

也可以往里拉东西

所以我们在使用队列的时候

最常用的方法就是 put 和 get 了

还是拿摸鱼为例

我们创建一个长度为 6 的队列

接着根据队列的长度创建了线程

每个线程都让它们处于守护状态

也就是需要的时候

马上执行

def queue_pool(): queue = Queue(6) for i in range(queue.maxsize): t = CustomThread(queue) t.setDaemon(True) t.start()

接着我们就可以用 put 方法

把我们想做的事情往队列里面塞

比如这里我们想要摸鱼

for i in range(20): queue.put(moyu)queue.join()def moyu(): print(" 开始摸鱼 %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))

要执行的话就需要去队列里面取了

q_method = self.__queue.get()q_method()self.__queue.task_done()

完整代码如下

import threadingimport timefrom queue import Queueclass CustomThread(threading.Thread): def __init__(self, queue): threading.Thread.__init__(self) self.__queue = queue def run(self): while True: q_method = self.__queue.get() q_method() self.__queue.task_done()def moyu(): print(" 开始摸鱼 %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))def queue_pool(): queue = Queue(5) for i in range(queue.maxsize): t = CustomThread(queue) t.setDaemon(True) t.start() for i in range(20): queue.put(moyu) queue.join()if __name__ == '__main__': queue_pool()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值