• python爬虫--多任务异步协程, 快点,在快点......


    多任务异步协程asyncio

    特殊函数:
    	- 就是async关键字修饰的一个函数的定义
    	- 特殊之处:
            - 特殊函数被调用后会返回一个协程对象
            - 特殊函数调用后内部的程序语句没有被立即执行
            
    - 协程
        - 对象。协程==特殊的函数。协程表示的就是一组特定的操作。
        
    - 任务对象
        - 高级的协程(对协程的进一步的封装)
            - 任务对象==协程==特殊的函数
                - 任务对象==特殊的函数
        - 绑定回调:
            - task.add_done_callback(task)
                - 参数task:当前回调函数对应的任务对象
                - task.result():返回的就是任务对象对应的特殊函数的返回值
                
    - 事件循环对象
        - 创建事件循环对象
        - 将任务对象注册到该对象中并且开启该对象
        - 作用:loop可以将其内部注册的所有的任务对象进行异步执行
    
    - 挂起:就是交出cpu的使用权。
    
    await:被用做在特殊函数的内部,在被阻塞的时候
    wait:给每一个任务赋予一个可被挂起的权限
    
    #【重点】在特殊函数内部的实现中,不可以出现不支持异步的模块(例如time,requests)代码,如果出现了,则会中断整个的异步效果!!!
    

    asyncio的使用

    import asyncio
    import time
    from time import sleep
    
    # 特殊函数
    async def get_request(url):
        print('正在下载: ',url)
        sleep(2)
        print('下载完毕: ',url)
        return 'page_text'
    
    # 回调函数,普通函数
    def parse(task):
        # 参数表示任务对象
        print('i am callback',task.result())
    
    
    start = time.time()
    # 调用特殊函数
    func = get_request('www.xx.com')
    
    # 创建任务对象
    task = asyncio.ensure_future(func)
    
    # 给任务对象绑定回调函数
    task.add_done_callback(parse)
    
    # 创建一个事件循环对象
    loop = asyncio.get_event_loop()
    
    # 让loop执行一个任务
    loop.run_until_complete(task)
    
    print("总耗时:",time.time()-start) #总耗时: 2.0017831325531006
    

    多任务协程

    import asyncio
    import time
    
    # 特殊函数
    async def get_request(url):
        print('正在下载',url)
        # time.sleep(2) 不支持异步的模块 会中断整个的异步效果
        await asyncio.sleep(2)
        print('下载完成',url)
        return 'page_text'
    
    def parse(task):
        print(task.result())
    
    
    start = time.time()
    urls = ['www.xxx1.com','www.xxx2.com','www.xxx3.com']
    
    tasks = []  #存放多任务
    for url in urls:
        # 调用特殊函数
        func = get_request(url)
    
        # 创建任务对象
        task = asyncio.ensure_future(func)
    
        # 给任务对象绑定回调函数
        task.add_done_callback(parse)
        tasks.append(task)
    
    # 创建事件循环对象
    loop = asyncio.get_event_loop()
    
    # 执行任务
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start) #2.0015313625335693
    
    

    aiohttp的使用

    - requests一定是不支持异步
    - aiohttp是一个支持异步的网络请求模块
        - 环境安装
        - 编码流程:
            - 大致的架构:
                 with aiohttp.ClientSession() as s:
                    #s.get(url,headers,params,proxy="http://ip:port")
                    with s.get(url) as response:
                        #response.read()二进制(.content)
                        page_text = response.text()
                        return page_text
                    
        - 补充细节
             - 在每一个with前加上async
             - 需要在每一个阻塞操作前加上await
                    async with aiohttp.ClientSession() as s:
                        #s.get(url,headers,params,proxy="http://ip:port")
                        async with await s.get(url) as response:
                            #response.read()二进制(.content)
                            page_text = await response.text()
                            return page_text
    
    

    异步协程爬虫案例

    # 需求用多任务异步协程获取百度,搜狗,京东,淘宝的页面源码数据,并简单解析
    import asyncio
    import requests
    import time
    from lxml import etree
    urls = ['https://www.baidu.com','http://www.taobao.com/','http://www.jd.com/','https://www.sogou.com/']
    headers={
        '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'
    }
    # 特殊函数
    async def get_request(url):
        print('正在下载',url)
        page_text = requests.get(url,headers=headers).text
        print(url,'下载完成')
        return page_text
    
    # 回调函数
    def parse(task):
        page_text = task.result()
        tree = etree.HTML(page_text)
        div = tree.xpath('//div')
        print(div)
    
    start = time.time()
    tasks = []#存放多任务
    for url in urls:
        func = get_request(url)
        task = asyncio.ensure_future(func)
        task.add_done_callback(parse)
        tasks.append(task)
    
    # 创建事件要在循环外
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    
    print('总耗时:',time.time()-start)
    
    #根据结果发现执行并不是异步,原因是requests不是异步模块,所以整个程序不会异步执行
    

    基于aiohttp的多任务协程的爬虫

    # 需求用多任务异步协程获取百度,搜狗,京东,淘宝的页面源码数据,并简答解析
    import asyncio
    import requests
    import time
    import aiohttp
    from lxml import etree
    urls = ['https://www.baidu.com','http://www.taobao.com/','http://www.jd.com/','https://www.sogou.com/']
    headers={
        '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'
    }
    # 特殊函数
    async def get_request(url):
        async with aiohttp.ClientSession() as s:
            # s.get(url,headers,params,proxy="http://ip:port")
            async with await s.get(url,headers=headers) as response:
                print('正在下载', url)
                # response.read()二进制(.content)
                page_text = await response.text()
                print(url, '下载完成')
                return page_text
    
    # 回调函数
    def parse(task):
        page_text = task.result()
        tree = etree.HTML(page_text)
        div = tree.xpath('//div')
        print(div)
    
    start = time.time()
    tasks = []#存放多任务
    for url in urls:
        func = get_request(url)
        task = asyncio.ensure_future(func)
        task.add_done_callback(parse)
        tasks.append(task)
    
    # 创建事件要在循环外
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    
    print('总耗时:',time.time()-start) #总耗时: 3.0848371982574463
    
  • 相关阅读:
    一行代码教你屏蔽你的博客广告
    一步一步教你给博客主页添加自定义炫酷效果
    让资源管理器变得像Chrome一样标签化
    weblayer组件介绍
    Tiny模板编辑器
    Tiny流程编辑器
    Tiny界面编辑器
    Tiny模板运行器
    org.tinygroup.pageflowbasiccomponent-页面流
    Tiny服务编辑器
  • 原文地址:https://www.cnblogs.com/tangjian219/p/12002525.html
Copyright © 2020-2023  润新知