zoukankan      html  css  js  c++  java
  • 单线程多任务异步协程

    目录

      1. 概念讲解

      2. 多任务异步协程理解

      3.基于aiohttp模块异步网络请求实现数据爬取及数据解析

    一、需要了解的概念

      特殊函数:如果async修饰了一个函数的定义,那么该函数就变成了一个特殊函数,

        特殊之处:特殊函数被调用后函数内部实现语句不会被立即执行 

        该函数调用之后会返回一个协程对象   

      协程对象:特殊函数调用后可以返回一个协程对象

        协程 == 特殊函数

      任务对象:对协程对象的进一步封装,就是一个高级协程对象

        任务对象 == 协程对象 == 特殊的函数

        绑定回调:task.add_done_callback(parse) #parse就是一个回调函数

          parse的定义:

            parse必须又一个参数,该参数表示的就是回调函数对应的任务对象

            task.result(): 就是特殊函数的的返回值

      事件循环对象:可以让特殊函数内部的语句执行

        该对象内部必须注册的是任务对象,当事件循环开启后其内部注册的任务对象就可以基于异步被执行

      ps: 在特殊函数每部不可以出现不支持异步代码对应的模块

    定义如下:

    import asyncio
    import time
    
    urls = [
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
    ]
    
    # 特殊函数
    async def get_request(url):
        print('正在请求:',url)
        time.sleep(2)
        print('请求结束;',url)
        return 'bobo'
    
    #对调函数
    def parse(task): #task 该回调函数对应的任务对象
        print(' I am callback')
        print(task.result()) #result返回的就是特殊函数的返回值
    
    #返回了一个协程对象
    c = get_request('www.1.com')
    
    #任务对象
    task = asyncio.ensure_future(c)
    
    #给任务对象绑定回调,任务对象执行完后才能被执行
    task.add_done_callback(parse)
    
    #创建一个事件循环对象
    loop = asyncio.get_event_loop()
    
    #需要将任务对象注册到事件循环对象中且需要启动循环对象
    loop.run_until_complete(task)

    二、多任务异步协程过程理解

    import asyncio
    import time
    
    urls = [
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
    ]
    
    start = time.time()
    # 特殊函数
    #!!!特殊函数内部不可以出现不支持异步的模块代码,如果出现了则会中断所有的异步代码
    async def get_request(url):
        print('正在请求:',url)
        #time.sleep(2)
        await asyncio.sleep(2) #await 遇到阻塞的时候需要阻塞然后再走后续代码
        print('请求结束;',url)
        return 'bobo'
    
    #任务列表
    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当任务对象遇到阻塞的时候允许挂起,把cpu的使用权交出来 print('耗时',time.time()-start)

    三、基于aiohttp模块异步网络请求实现数据爬取及数据解析 

    1. aiphttp模块使用详解

    pip install aiohttp 编码: 基本架构: with aiohttp.ClientSession() as s:
    #s就是一个请求对象 with s.get(url) as response: page_text = response.text() #read() ==> content json没变 return page_text 补充细节 在每个with前加async 在每个阻塞前加await async with aiohttp.ClientSession() as s: #s就是一个请求对象 async with await s.get(url) as response: page_text = await response.text() #read() ==> content json没变 return page_text

    2.aioihttp使用案列及说明及数据解析

    import asyncio
    import time
    import requests
    import aiohttp
    from lxml import etree
    urls = [
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
    ]
    
    start = time.time()
    # 特殊函数
    #!!!特殊函数内部不可以出现不支持异步的模块代码,如果出现了则会中断所有的异步代码
    async def get_request(url):
        #requests模块是不支持异步的
        # page_text = requests.get(url).text
        # return page_text
        async with aiohttp.ClientSession() as s: #s就是一个请求对象
            async with await s.get(url) as response: #get/post(url,data/parms,headers,proxy='http://ip:port')
                page_text = await response.text() #read() ==> content json没变
                return page_text
    
    #定义回调函数
    def parse(task):
        page_text = task.result()
        tree = etree.HTML(page_text)
        print(tree.xpath('//a/text()'))
    
    #任务列表
    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)
  • 相关阅读:
    Asp.Net生成二维码(中间加logo)
    简单的图片上传
    C#读取路径
    Asp.Net读取配置文件
    C#监听服务
    jQuery 遍历--siblings() 方法、each() 方法
    Window 6大内置对象
    MySQL中几个重要的参数
    DNS构建实战(下篇)
    DNS构建实战(上篇)
  • 原文地址:https://www.cnblogs.com/guniang/p/11718937.html
Copyright © 2011-2022 走看看