隐藏页面特效

线程池,协程,多任务异步

1|0基于flask的server断服务器


from flask import Flask, render_template from time import sleep app = Flask(__name__) @app.route('/index') def index(): sleep(2) return render_template('test.html') @app.route('/home') def index1(): sleep(2) return render_template('test.html') @app.route('/login') def index2(): sleep(2) return render_template('test.html') if __name__ == '__main__': app.run(threaded=True) # 旧版本需要加上这个才能开启多线程

2|0线程池


from multiprocessing.dummy import Pool import requests import time from lxml import etree start = time.time() urls = [ 'http://127.0.0.1:5000/index', 'http://127.0.0.1:5000/home', 'http://127.0.0.1:5000/login', ] pool = Pool(3) # 开启3个线程 # 回调函数会异步处理列表中的每一个列表元素 def get_request(url): page_text = requests.get(url).text return page_text page_text_list = pool.map(get_request, urls) # 异步解析数据 def parse_text(page_text): tree = etree.HTML(page_text) tree.xpath('//*[@id="feng"]') pool.map(parse_text, page_text_list) print('总耗时', time.time()-start)

3|0协程的基本操作


import asyncio import time async def get_request(url): print('正在请求', url) time.sleep(2) print('请求结束', url) return 'go go go go' # 创建一个协程对象 c = get_request('www.1.com') # 创建一个任务对象 task = asyncio.ensure_future(c) # 创建一个事件循环对象 loop = asyncio.get_event_loop() # 将任务对象装载到事件循环对象这个容器中且启动事件循环 loop.run_until_complete(task)

4|0任务对象的回调函数


import asyncio import requests import time async def get_request(url): print('正在请求', url) time.sleep(2) print('请求结束', url) return 'go go go go' def parse(task): # result()返回的就是任务对象表示的特殊函数内部的返回值 result = task.result() print(result) c = get_request('www.1.com') task = asyncio.ensure_future(c) # 给任务对象绑定一个回调 目的是为了函数return获取返回值 # 该回调函数必须要有一个参数,这个参数表示的就是add_done_callback的调用者 # 回调函数一定是在任务对象完全执行结束后才会被调用执行 task.add_done_callback(parse) loop = asyncio.get_event_loop() loop.run_until_complete(task)

5|0多任务协程


import asyncio import requests import time start = time.time() async def get_request(url): print('正在请求', url) # time.sleep(2) await asyncio.sleep(2) print('请求结束', url) return 'go go go go' urls = [ 'http://127.0.0.1:5000/index', 'http://127.0.0.1:5000/home', 'http://127.0.0.1:5000/login', ] tasks = [] for url in urls: c = get_request(url) task = asyncio.ensure_future(c) tasks.append(task) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) # wait挂起 print('总耗时', time.time()-start) # 上面代码出现的问题: # 1.多任务的模式并没有实现真正的异步 # 2.wait()方法的作用

6|0多任务的异步爬虫


import requests import time import asyncio import aiohttp from lxml import etree start = time.time() urls = [ 'http://127.0.0.1:5000/index', 'http://127.0.0.1:5000/home', 'http://127.0.0.1:5000/login', ] # async def get_request(url): # # requests是一个不支持异步的模块 # page_text = await requests.get(url) # return page_text async def get_request(url): async with aiohttp.ClientSession() as sess: #实例化了一个请求对象 async with await sess.get(url) as response: #get/post和requests的get/post用法几乎一致 page_text = await response.text() #byte类型的数据使用read() return page_text def parse(task): page_text = task.result() tree = etree.HTML(page_text) tree.xpath('//a[@id="feng"]') tasks = [] for url in urls: c = get_request(url) task = asyncio.ensure_future(c) task.add_done_callback(parse) tasks.append(task) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) print('总耗时', time.time()-start)

7|0笔记


异步爬虫的实现方式 - 线程池 - 多任务的异步协程 - 多线程(生产者消费者模型) 协程asyncio - 特殊的函数 - 如果一个函数的定义被async关键字装饰,则该函数就是一个特殊函数 - 特殊之处: - 1.特殊函数调用后,函数内部的程序语句没有被立即执行 - 2.特殊函数调用后会返回一个协程对象 - 协程 - 对象,可以调用特殊函数返回一个协程。 - 协程 == 特殊的函数 == 一组指定形式的操作 - 协程 == 一组指定形式的操作 - 任务 - 对象. 任务对象其实就是一个高级的协程对象 - 任务对象 == 协程 == 一组指定形式的操作 - 任务 == 一组指定形式的操作 - 特殊的机制: - 绑定一个回调函数 - 事件循环(核心) - 对象asyncio.get_event_loop() - 事件循环你可以暂且把它当做一个载体或者容器 - 将协程或者任务对象装载在事件循环这个容器中 - run_until_complete - 开启事件循环 - async - wait() - 用来对tasks这个任务列表进行指定操作. - wait可以将tasks任务列表中每一个任务对象一次赋予可挂起的权限 - 挂起:可以让当前被执行的任务对象交出cpu的使用权 - 当任务列表被wait方法修饰处理后,依然没有出现异步的效果 - 在特殊函数内部的实现语句中不可以出现不支持异步模块的代码,否则会中断异步效果 - await - 是可以确保在异步的过程中,让阻塞操作可以执行完毕 支持异步的网络请求模块 - aiohttp - pip install aiohttp - 代码实现: - 第一步:编写基本架构 async def get_request(url): with aiohttp.ClientSession() as sess: #实例化了一个请求对象 with sess.get(url) as response: #get/post和requests的get/post用法几乎一致 page_text = response.text() #byte类型的数据使用read() return page_text - 第二步:补充细节 - 在每个with前加上async关键字 - 在每一步阻塞前加上await关键字 async def get_request(url): async with aiohttp.ClientSession() as sess: #实例化了一个请求对象 async with await sess.get(url) as response: #get/post和requests的get/post用法几乎一致 page_text = await response.text() #byte类型的数据使用read() return page_text 流程: 首先确保任务列表可以被挂起,然后依次执行,当执行任务列表里面的A任务时,遇到await asyncio.sleep(2),遇到阻塞, A任务对象挂起,交出CPU使用权,执行任务列表里面B任务对象获得使用权,遇到await asyncio.sleep(2),遇到阻塞, B任务对象挂起,交出CPU使用权,执行任务列表里面C任务对象获得使用权,遇到await asyncio.sleep(2),遇到阻塞, C任务对象挂起,交出CPU使用权,可能C还没执行完的时候,A任务对象开始从之前阻塞的地方往下执行。后面B.C同样

__EOF__

本文作者404 Not Found
本文链接https://www.cnblogs.com/weiweivip666/p/14028177.html
关于博主:可能又在睡觉
版权声明:转载请注明出处
声援博主:如果看到我睡觉请喊我去学习
posted @   我在路上回头看  阅读(249)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示