爬虫的单线程+多任务异步协程:asyncio 3.6

单线程+多任务异步协程:asyncio 3.6

  • 事件循环
    • 无限循环的对象.事件循环中最终需要将一些 特殊的函数(被async关键字修饰的函数) 注册在该对象中.
  • 协程
    • 本质上是一个对象.可以把协程对象(特殊的函数)注册到事件循环中
  • 任务对象
    • 就是对协程对象进一步的封装.
  • 绑定回调: task.add_done_callback(func)
    • func(task):task参数表示的就是绑定的任务对象
    • task.result():返回就是任务对象对应的特殊函数内部的返回值
    • 回调多被用作于爬虫中的解析方法
  • await
    • 在任务对象对应的特殊函数内部的实现语句中,如果出现了阻塞的操作,则必须使用await进行修饰
  • 异步操作的体现
    • 当将多个协程对象(特殊的函数)注册到事件循环中后,事件循环开启后,则会循环执行其内部的协程对象们
    • 假如事件循环对象在执行某一个协程对象时,发生了阻塞,则事件循环对象不会等待阻塞结束,反而会执行下一个协程对象
  • aiohttp:支持异步的网络请求模块
    • 中文文档
      • https://www.cntofu.com/book/127/aiohttp%E6%96%87%E6%A1%A3/ClientUsage.md
    • 环境安装 pip或者直接pycharm安装都可以
    • 如何进行UA伪装:
      • session.get(url,headers)
    • 参数的封装
      • session.get(url,headers,data/params)
    • 代理IP方式:
      • session.get(url,proxy="http://ip:port")
  • 简单示例

    import asyncio
    #特殊的函數:该函数调用后,函数内部的程序语句不会被执行,但是该函数调用会返回一个协程对象
    async def test():print('i am test()')print('i am test()')print('i am test()')#调用该特殊函数,让其返回一个协程对象
    c = test()#创建一个事件循环对象
    loop = asyncio.get_event_loop()#将协程对象注册到事件循环对象中,并且开启事件循环
    loop.run_until_complete(c)print(c)
  • 任务对象的使用

    import asyncio
    #特殊的函數:该函数调用后,函数内部的程序语句不会被执行,但是该函数调用会返回一个协程对象
    async def test():print('i am test()')#调用该特殊函数,让其返回一个协程对象
    c = test()#将协程对象封装到任务对象中
    task = asyncio.ensure_future(c)#创建一个事件循环对象
    loop = asyncio.get_event_loop()#将任务对象注册到事件循环对象中,并且开启事件循环
    loop.run_until_complete(task)
  • 任务对象绑定回调函数

    import asyncio
    #特殊的函數:该函数调用后,函数内部的程序语句不会被执行,但是该函数调用会返回一个协程对象
    async def test():print('i am test()')return 'hello bobo'#任务对象的回调函数,参数task表示的就是任务对象
    def func(task):# print('i am task callback!')print(task.result()) #返回的是任务对象对应的特殊函数的返回值#调用该特殊函数,让其返回一个协程对象
    c = test()#将协程对象封装到任务对象中
    task = asyncio.ensure_future(c)#给任务对象绑定一个回调函数
    task.add_done_callback(func)#创建一个事件循环对象
    loop = asyncio.get_event_loop()#将任务对象注册到事件循环对象中,并且开启事件循环
    loop.run_until_complete(task)
  • 多任务异步协程

    import asyncio
    import time
    #函数内部不可以出现不支持异步模块的代码
    #该函数内部的异步操作必须使用await进行修饰
    async def request(url):print('正在下载:',url)# time.sleep(2) #time模块是一个不支持异步的模块await asyncio.sleep(2) #asyncio模块中提供的一个支持异步的阻塞方法print(url,'下载完毕!')return url#创建一个回调函数
    def callback(task):#返回的是任务对象对应的特殊函数的返回值print(task.result())urls = ['www.1.com','www.2.com','www.3.com','www.4.com',
    ]
    #记录开始时间
    start = time.time()
    #任务列表
    tasks = []
    for url in urls:#调用该特殊函数,让其返回一个协程对象c = request(url)#将协程对象封装到任务对象中task = asyncio.ensure_future(c)# 给任务对象绑定回调task.add_done_callback(callback)#将任务对象添加到列表中tasks.append(task)#创建一个事件循环对象
    loop = asyncio.get_event_loop()
    #将任务对象列表注册到事件循环对象中,并且开启事件循环
    loop.run_until_complete(asyncio.wait(tasks))
    ##记录结束时间
    print(time.time()-start)
  • 单线程+多任务异步协程的爬虫

    import asyncio
    import requests
    import time
    import aiohttp
    from lxml import etree
    urls = ['http://localhost:5000/bobo','http://localhost:5000/jay','http://localhost:5000/tom','http://localhost:5000/bobo','http://localhost:5000/jay','http://localhost:5000/tom'
    ]# async def get_page(url):
    #     #requests模块是一个不支持异步的模块,解决方法就是使用一个支持异步的模块进行请求发送
    #     page_text =  requests.get(url=url).text
    #     return page_textasync def get_page(url):#使用aiohttp进行请求发送#实例化了一个发送网络请求的对象async with aiohttp.ClientSession() as session:#该函数内部的异步操作必须使用await进行修饰async with await session.get(url) as response:#获取响应数据(页面源码数据)page_text = await response.text()# print(page_text)return page_text
    #数据解析的操作需要在回调函数中实现
    def parse(task):page_text = task.result()tree = etree.HTML(page_text)parse_data = tree.xpath('//body/text()')[0]print(parse_data)start = time.time()
    tasks = []
    for url in urls:#调用该特殊函数,让其返回一个协程对象c = get_page(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)
  • 单线程+多任务异步协程的应用

    #爬取喜马拉雅中的相声音频
    import requests
    import aiohttp
    import asyncio
    #通用的url模板
    url = 'https://www.ximalaya.com/revision/play/album?albumId=19366477&pageNum=%d&sort=1&pageSize=2'
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
    }
    #获取了所有即将被下载的音频连接
    urls = []
    for page in range(1,3):new_url = format(url%page)dic_obj = requests.get(url=new_url,headers=headers).json()for dic in dic_obj['data']['tracksAudioPlay']:audio_url = dic['src']urls.append(audio_url)#特殊的函數:该函数调用后,函数内部的程序语句不会被执行,但是该函数调用会返回一个协程对象
    async def get_audio_data(url):#使用aiohttp进行请求发送#实例化了一个发送网络请求的对象async with aiohttp.ClientSession() as s:#该函数内部的异步操作必须使用await进行修饰async with await s.get(url=url,headers=headers) as response:audio_data = await response.read()  #read()返回的是二进制形式的响应数据return {'data':audio_data,'url':url}#任务对象的回调函数,进行数据的持久化存储
    def saveData(task):dic_obj = task.result()name = dic_obj['url'].split('/')[-1]data = dic_obj['data']with open(name,'wb') as fp:fp.write(data)print(name+'下载完毕!')tasks = []
    for url in urls:#调用该特殊函数,让其返回一个协程对象c = get_audio_data(url)#将协程对象封装到任务对象中task = asyncio.ensure_future(c)# 给任务对象绑定回调函数task.add_done_callback(saveData)#将任务对象添加到列表中tasks.append(task)
    #创建一个事件循环对象
    loop = asyncio.get_event_loop()
    #将任务对象列表注册到事件循环对象中,并且开启事件循环
    loop.run_until_complete(asyncio.wait(tasks))

转载于:https://www.cnblogs.com/Godisgirl/p/11025195.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/424489.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法十——深度优先搜索和广度优先搜索

文章出处:极客时间《数据结构和算法之美》-作者:王争。该系列文章是本人的学习笔记。 搜索算法 算法是作用于数据结构之上的。深度优先搜索、广度优先搜索是作用于图这种数据结构之上的。图上的搜索算法可以理解为从一个顶点到另外一个顶点。 常用的搜…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol 52][第35篇]给针对ECDLP问题的Pollard rho,parallel Pollard rho攻击的一个粗略的描述

这是一系列博客文章中最新的一篇,该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 [1] http://www.cs.bris.ac.uk/~nigel/Crypto_Book/book.ps (pages 208 - 214) 转载连接:https…

spring学习(16):使用接口

目录结构 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/P…

交易系统高并发下的幂等性设计原则

一、介绍 幂等性就是针对同一个请求&#xff0c;不管该请求被提交了多少次&#xff0c;该请求都将被视为同一个请求&#xff0c;服务端不应该将同一个请求进行多次处理&#xff0c;以确认处理逻辑的正确性&#xff0c;针对交易性系统幂等性的设计尤为重要&#xff0c;否则由于网…

工程中选择数据结构和算法的依据

1. 时间、空间复杂度不能和性能划等号 时间、空间复杂度不是时间执行和内存消耗的精确值。它们只是表示了随着数据量的增长&#xff0c;时间、空间的增长趋势。 代码的执行时间有时不跟时间复杂度成正比。我们常说算法是O(nlogn),O(n2n^2n2)这些都是基于大数据量&#xff08;…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第36篇]Index Calculus算法

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 我们这篇博客继续描述一种数学攻击&#xff0c;这种数学攻击被叫做Index Calculus(IC)算法。 注意这里Index…

DS博客作业07--查找

1.本周学习总结 1.思维导图 2.谈谈你对树结构的认识及学习体会。 查找是一种跟我们生活息息相关的算法&#xff0c;最典型的例子就是搜索引擎&#xff0c;而评价一种查找算法的优劣的关键就是查找速度&#xff0c;生活中我们往往要在大量数据查找自己所需要的东西&#xff0c;如…

easyUI学习笔记二

1&#xff0e; 拖拉大小 <!DOCTYPE html> <html> <head><title>easyui学习</title><script type"text/javascript" src jquery-easyui/jquery.min.js> </script><script type"text/javascript" src jquer…

C语言—每日选择题—Day62

隔一天更新解析 第一题 1. 在使用标准C库时&#xff0c;下面哪个选项使用只读模式打开文件&#xff1f; A&#xff1a;fopen("foo.txt", "r") B&#xff1a;fopen("foo.txt", "r") C&#xff1a;fopen("foo.txt", "w&…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第37篇]The Number Field Sieve

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 转载链接&#xff1a;https://www.cnblogs.com/zhuowangy2k/p/12245636.html

大二下学期软件工程概论总结

软件工程概论这门课可以算是我本学期最辛苦的一门课了。但与此同时这门课给我带来的收获和其他课程相比&#xff0c;也不是一个量级的。 这学期我通过课上的学习与作业项目的完成过程&#xff0c;了解到软件开发由项目的确定到项目的需求分析&#xff0c;再到概要&#xff0c;详…

70. Climbing Stairs

输入&#xff1a;台阶数量n 输出&#xff1a;有多少种走法 规则&#xff1a;每次可以上一个台阶或者两个台阶 分析&#xff1a;想明白一件事情。如果现在在第k个台阶&#xff0c;那下一步可以到达第k1个台阶&#xff0c;或者第k2个台阶。换句话说想要到达第k个台阶&#xff0c;…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第39篇]侧信道攻击和故障攻击有什么区别

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 侧信道攻击(Side-channel attacks, SCA)是一类攻击者尝试通过观察侧信道泄露来推测目标计算的信息。&#x…

面向对象:包装类、对象处理、类成员

包装类 Java是面向对象编程语言&#xff0c;但也包含了八种基本的数据类型&#xff0c;这八种基本的数据类型不支持面向对象的编程机制&#xff0c;基本的数据类型也不具备对象的特性&#xff1a;没有成员变量、方法被调用。所有类型的变量都继承Object类&#xff0c;都可以当成…

mysql-安装报错计算机中丢失MSVCR100.dll文件丢失

https://blog.csdn.net/weirdo_world/article/details/82393330

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]40一般来说SPA和DPA的区别是什么

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 电磁(Electronmagnetic, EM)功率分析攻击被划分成两种类型的攻击&#xff0c;简单功率分析(SPA)或者差分功率…

LDAP入门

LDAP入门 首先要先理解什么是LDAP&#xff0c;当时我看了很多解释&#xff0c;也是云里雾里&#xff0c;弄不清楚。在这里给大家稍微捋一捋。首先LDAP是一种通讯协议&#xff0c;LDAP支持TCP/IP。协议就是标准&#xff0c;并且是抽象的。在这套标准下&#xff0c;AD&#xff08…

关于Java中的HashMap

1 容量总是2次幂 /*** Returns a power of two size for the given target capacity.*/static final int tableSizeFor(int cap) {int n cap - 1;n | n >>> 1;n | n >>> 2;n | n >>> 4;n | n >>> 8;n | n >>> 16;return (n <…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]41所有的侧信道分析都是能量分析吗

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 侧信道攻击(SCA)利用在密码算法的物理实现上下文中获得的信息&#xff0c;而不是针对理论弱点的经典密码分析…

spring学习(22):分层架构

pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 …