场景:目标抓取1万条数据
执行过程如下:
请求url
得到相应
从相应中提取内容
存到本地
按照逻辑是线性过程,效率太低
可采用异步操作,可考虑3种方式:多线程,多进程,协程
1.快速学会多线程
2.快速学会多进程
3.线程池和进程池
4.拔光新发地
5.协程
6.多任务异步协程实现
7.aiohttp模块详解
8.扒光一本小说
9.综合训练-抓取一部电影
进程是资源单位,每一个进程至少要有一个线程
线程是执行单位
多线程
# 线程,进程 # 进程是资源单位,每一个进程至少要有一股线程 # 线程执行单位 # 启动每一个程序默认都会有一股主线程 # def func(): # for i in range(1000): # print("func",i) # # if __name__ == "__main__": # func() # for i in range(1000): # print("main",i) # 多线程 from threading import Thread # 多线程类 # # # def func(): # for i in range(1000): # print("第一个线程", i) # # # def func_sec(): # for ts2 in range(1000): # print("第二个线程:", ts2) # # # if __name__ == "__main__": # # 调用多线程方法,创建线程,给线程安排任务 # t = Thread(target=func()) # # 多线程状态为可以开始工作状态,具体的执行时间由CPU决定 # t.start() # # 创建第二个线程 # t2 = Thread(target=func_sec()) # t2.start() # for i in range(1000): # print("主线程", i) # 多线程第二套写法:第二套写法比较主流 # 写一个类,继承Thread方法,那么这个类也是多线程类 class MyThread(Thread): # run方法重写,固定的 def run(self): for i in range(1000): print('第一个子线程', i) if __name__ == '__main__': thread_first = MyThread() # thread_first.run() 这个不能这样调用,调用后,就是单线程 # 开启线程 thread_first.start() for i in range(1000): print('主线程', i)
多进程
# 相对于多线程而言,多进程实际用的比较少,因为开辟进程比线程消耗资源要多,耗费内存,不推荐多进程 from multiprocessing import Process def func(): for a in range(1000): print("子进程", a) if __name__ == '__main__': p = Process(target=func()) p.start() for b in range(1000): print("主进程", b)
线程池和进程池
# 线程池:一次性开辟一些线程,我们用户直接给线程池提交任务,线程任务的调度交给线程池来完成 # 开辟一个50个线程池, # ThreadPoolExecutor是线程池,ProcessPoolExecutor是进程池 from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor def func(name): for i in range(1000): print(name, i) if __name__ == '__main__': # 创建线程池,创建一个由50个线程组成的池程池 with ThreadPoolExecutor(50) as t: # 例如有1万个任务 for i in range(100): # 要给线程池提交任务,给线程传送参数,url等 t.submit(func,name=f"线程{i}") # 等待线程池的任务全部执行完成,才继续执行(这叫守护的概念) print("123")