python爬虫14 | 就这么说吧,如果你不懂python多线程和线程池,那就去河边摸鱼!
你知道吗?
在我的心里
你是多么的重要
就像
恩
请允许我来一段 freestyle
你们准备好了妹油
你看
这个碗
它又大又圆
就像
这条面
它又长又宽
你们
在这里
看文章
觉得 很开心
就像
我在这里
给你们
写文章
觉得很开心
skr~~
不好意思
走错片场了
ok..
接下来,就是
咱们在上一次的
python爬虫13 | 秒爬,这多线程爬取速度也太猛了,这次就是要让你的爬虫效率杠杠的
了解了一些 python 高效爬虫的概念
比如多线程、多进程、协程等
那么我们这一篇就开始了解多线程的具体使用
在 python 中
常用的多线程的模块有这么几个
_thread
threading
Queue
之前有个 thread 模块
被 python3 抛弃了
改名为 _thread
但其实 _thread 也没什么人用
因为 _thread 有的 threading 都有
_thread 没有的 threading 依然有
那么接下来我们就先来玩玩 threading 吧
在此之前
(请允许小帅b又开始吹水了~)
介绍一下 小帅b 的一点背景
小帅b呢
平常上班时间都会去河边摸鱼
每天得摸 20 条鱼
一条一条的摸
为的是什么
为的是安抚这些鱼的心情
这样以后送到餐前的红烧鱼才更加美味
恩
小帅b每天得摸 20 条鱼
每隔一秒钟摸一条
也就是这样
import time
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 -= 1
if __name__ == '__main__':
moyu_time('小帅b',1,20)
后来
小帅b知道了多线程
拍脑一想
我靠
应该把小明和小红拉过来
让他们一起帮我摸鱼啊
也就是让小明和小红同时一人摸 10 条鱼
想想就开心
在 小帅b 的威逼利诱下
他们俩不情愿的手拉着手来到了河边
小帅b看小红是女生
就让小红每摸一条鱼休息 2 秒钟
而小明每摸一条鱼休息 1 秒钟
先扔一段代码给你
# encoding = utf-8
import threading
import 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再也不用摸鱼了
后来小明和小红都不乐意了
凭什么就我们两个摸鱼
这时候 小帅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!!!
这可不行
因为频繁的创建线程 销毁线程
非常的浪费资源
所以呢
应该把他们放到池子里面去一起洗澡
哈,也就是
线程池
通过线程池就可以重复利用线程
不会造成过多的浪费
在 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 -= 1
if __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:10
xiaoshuaib1 开始摸鱼 2019-03-10 23:30:11
xiaoshuaib1 开始摸鱼 2019-03-10 23:30:12
xiaoshuaib2 开始摸鱼 2019-03-10 23:30:13
xiaoshuaib2 开始摸鱼 2019-03-10 23:30:14
xiaoshuaib2 开始摸鱼 2019-03-10 23:30:15
xiaoshuaib3 开始摸鱼 2019-03-10 23:30:16
xiaoshuaib3 开始摸鱼 2019-03-10 23:30:17
xiaoshuaib3 开始摸鱼 2019-03-10 23:30:18
xiaoshuaib4 开始摸鱼 2019-03-10 23:30:19
xiaoshuaib4 开始摸鱼 2019-03-10 23:30:20
xiaoshuaib4 开始摸鱼 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 threading
import time
from queue import Queue
class 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()
本篇就到这里吧
ps:本来想接着写一下用多线程来爬取网站的,篇幅有限,咱们下一篇再见
peace
点个好看啊~~(破音)
python爬虫14 | 就这么说吧,如果你不懂python多线程和线程池,那就去河边摸鱼!的更多相关文章
- Python多线程、线程池及实际运用
我们在写python爬虫的过程中,对于大量数据的抓取总是希望能获得更高的速度和效率,但由于网络请求的延迟.IO的限制,单线程的运行总是不能让人满意.因此有了多线程.异步协程等技术. 下面介绍一下pyt ...
- Python爬虫之路——简单网页抓图升级版(添加多线程支持)
转载自我的博客:http://www.mylonly.com/archives/1418.html 经过两个晚上的奋斗.将上一篇文章介绍的爬虫略微改进了下(Python爬虫之路--简单网页抓图),主要 ...
- Python 多线程和线程池
一,前言 进程:是程序,资源集合,进程控制块组成,是最小的资源单位 特点:就对Python而言,可以实现真正的并行效果 缺点:进程切换很容易消耗cpu资源,进程之间的通信相对线程来说比较麻烦 线程:是 ...
- python(13)多线程:线程池,threading
python 多进程:多进程 先上代码: pool = threadpool.ThreadPool(10) #建立线程池,控制线程数量为10 reqs = threadpool.makeRequest ...
- Python爬虫入门教程 13-100 斗图啦表情包多线程爬取
斗图啦表情包多线程爬取-写在前面 今天在CSDN博客,发现好多人写爬虫都在爬取一个叫做斗图啦的网站,里面很多表情包,然后瞅了瞅,各种实现方式都有,今天我给你实现一个多线程版本的.关键技术点 aioht ...
- python爬虫简单实现,并在java中调用python脚本,将数据保存在json文件中
# coding:utf-8 import urllib2 from bs4 import BeautifulSoup import json import sys reload(sys) sys.s ...
- python DBUtils 线程池 连接 Postgresql(多线程公用线程池,DB-API : psycopg2)
一.DBUtils DBUtils 是一套允许线程化 Python 程序可以安全和有效的访问数据库的模块,DBUtils提供两种外部接口: PersistentDB :提供线程专用的数据库连接,并自动 ...
- python-多线程和线程池
import threading # 点击查看它的用法 传统多线程方案会使用“即时创建, 即时销毁”的策略. from multiprocessing.dummy import Pool # 线程池 ...
- python爬虫16 | 你,快去试试用多进程的方式重新去爬取豆瓣上的电影
我们在之前的文章谈到了高效爬虫 在 python 中 多线程下的 GIL 锁会让多线程显得有点鸡肋 特别是在 CPU 密集型的代码下 多线程被 GIL 锁搞得效率不高 特别是对于多核的 CPU 来说 ...
随机推荐
- 产品架构model
- linux用户态和内核态通信之netlink机制【转】
本文转载自:http://blog.csdn.net/zcabcd123/article/details/8272360 这是一篇学习笔记,主要是对<Linux 系统内核空间与用户空间通信的实现 ...
- openstack封装待调试
- Istio 1.1部署实践
前提条件 正确安装配置Kubernetes集群 CentOS Linux release 7.5.1804 安装 下载istio 1.1版本 [root@vm157 ~]# wget https:// ...
- [Luogu 1052] noip 05 过河
[Luogu 1052] noip 05 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是 ...
- 多重背包(MultPack = ZeroOnePack + CompletePack)
HiHoCoder_offer6_04 题目4 : 奖券兑换 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi在游乐园中获得了M张奖券,这些奖券可以用来兑换奖品. ...
- SVN系列学习(一)-SVN的安装与配置
1.SVN的介绍 SVN是Subversion的简称,是一个开发源代码的版本控制系统,采用了分支管理系统. 文件保存在中央版本库,除了能记住文件和目录的每次修改以外,版本库非常像普通的文件服务器.你可 ...
- Struts2之一 初体验
Struts2 框架是基于MV模式开发的,它提供了一个核心控制器,用于对所有的请求进行统一处理,这个控制器是由一个名为FilterDispatcher的Servlet过滤器来充当的. 01.需要在we ...
- 第一次android混淆实战
第一次混淆,主要是因为引用本地第三方jar包的问题.虽然说本地第三方jar包自动避免混淆,但一些本地第三方jar包下的一些包要避免混淆.比如: 文中的com.org 这些包名都要避免混淆. 下面是我用 ...
- VC socket api使用引入
1.在创建项目时勾上windows socket api的使用 2.头文件 #pragma comment(lib,"WS2_32.lib") 3.初始化 WSADATA dat ...