zoukankan      html  css  js  c++  java
  • 多任务异步协程,asyncio及aiohttp

    要实现异步协程,需要满足几个条件:

      1,创建协程对象,且协程内部操作需要支持异步。

      2,创建任务对象,如需为协程执行结果进行进一步处理,则需要为任务对象绑定回调函数。

      3,创建事件循环,并将任务启动。

      1 import asyncio
      2 import requests
      3 from lxml import etree
      4 import aiohttp
      5 import os
      6 
      7 headers = {
      8 
      9     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
     10 }
     11 
     12 
     13 # 普通单线程,同步执行任务
     14 # url_ = 'https://www.qiushibaike.com/pic/page/{}/'
     15 # for i in range(1, 100):
     16 #     url = url_.format(i)
     17 #
     18 #     ret = requests.get(url=url, headers=headers).text
     19 #     tree = etree.HTML(ret)
     20 #     url_list = tree.xpath('//div[@id="content-left"]/div/div/a/img/@src')
     21 #     for url in url_list:
     22 #         name = url.split('/')[-1]
     23 #         print(name)
     24 #         img_url = 'https:' + url
     25 #         img = requests.get(img_url, headers=headers).content
     26 #         with open(os.path.join('qiutu',name), 'wb') as f:
     27 #             f.write(img)
     28 
     29 # 使用async修饰过的函数,调用函数时,函数不执行,而是生成了一个协程对象
     30 async def get_img(url):
     31     """
     32     # aiohttp的细节处理:
     33     # asnyc:硬性的语法要求关键字,应用aiohttp的代码模块
     34     # await: 会出现阻塞的操作的代码中,需要用await修饰
     35 
     36     """
     37 
     38     # ret = requests.get(url=url, headers=headers).text
     39     name = url.split('/')[-1]
     40 
     41     # 固定写法,aiohttp.ClientSession(),实例化一个异步请求对象
     42     async with  aiohttp.ClientSession() as aio:
     43         # 用该对象向url发送异步请求
     44         async with await aio.get(url=url, headers=headers) as ret:
     45             # 将响应对象(图片)读取为二进制流,以便存储。(.text().json().read())对应requests的(.text.json.content)
     46             res = await ret.read()
     47 
     48     return name, res
     49 
     50 
     51 # 定义一个回调函数(名字随意),回调函数接收该任务对象本身,(像self)
     52 def callback(task):
     53     # task.result()接收协程(特殊函数执行的返回结果,可进一步处理)
     54     name, res = task.result()
     55     # 将二进制流持久化成本地文件
     56     with open(os.path.join('qiutu', name), 'wb') as f:
     57         f.write(res)
     58     print(name, '下载完成')
     59 
     60 
     61 # 通过糗图百科通用页面url,生成十页数据,并将十页数据中的所有图片链接存到urls中
     62 urls = []
     63 url_ = 'https://www.qiushibaike.com/pic/page/{}/'
     64 for i in range(1, 10):
     65     page_url = url_.format(i)
     66     ret = requests.get(url=page_url, headers=headers).text
     67     # 通过xpath定位并获取糗图图片的src
     68     tree = etree.HTML(ret)
     69     url_list = tree.xpath('//div[@id="content-left"]/div/div/a/img/@src')
     70     # 将每个图片的url存到urls中
     71     for img_url in url_list:
     72         urls.append(img_url)
     73         print(img_url)
     74 
     75 tasks = []
     76 
     77 for url in urls:
     78     url = 'https:' + url
     79     # 执行协程对象函数(函数并不会真正去执行,而是生成一个协程对象)
     80     cor = get_img(url)
     81     # 将协程对象添加。生成一个任务对象
     82     # task = asyncio.create_task(cor)       # python3.7新加入
     83     task = asyncio.ensure_future(cor)
     84     # 为任务对象绑定添加一个回调函数,传入函数名
     85     task.add_done_callback(callback)
     86     # 将所有的任务对象添加到任务列表中
     87     tasks.append(task)
     88 
     89 # 获取当前事件循环对象(没有则创建),asyncio.new_event_loop()是创建事件循环
     90 loop = asyncio.get_event_loop()
     91 
     92 # run_until_complete:运行直到 future (可等待任务对象) 被完成。
     93 
     94 # 将任务列表加入事件循环,并发开始执行
     95 # 请注意此函数不会引发 asyncio.TimeoutError。当超时发生时,未完成的 Future 或 Task 将在指定秒数后被返回,指定timeout参数。
     96 loop.run_until_complete(asyncio.wait(tasks))
     97 
     98 # asyncio.gather:如果所有可等待对象都成功完成,结果将是一个由所有返回值聚合而成的列表。结果值的顺序与 aws 中可等待对象的顺序一致。
     99 # 如果发生超时,任务将取消并引发 asyncio.TimeoutError.
    100 # loop.run_until_complete(asyncio.gather(tasks))

    注意!:

      一个线程内最多大概可以注册500个协程。。任务数过多,需要多线程加异步协程实现。

  • 相关阅读:
    java操作生成jar包 和写入jar包
    jboss配置jndi连接池
    windows 域的LDAP查询相关举例
    LDAP error Code 及解决方法
    HDU 6417
    CF1299D Around the World
    codechef Chef and The Colored Grid
    Educational Codeforces Round 82 (Rated for Div. 2)
    CF1237F Balanced Domino Placements
    CF1254E Send Tree to Charlie
  • 原文地址:https://www.cnblogs.com/NoteBook3013/p/11109992.html
Copyright © 2011-2022 走看看