• 单线程+异步协程的简单爬虫模型


    event_loop:事件循环,相当于一个无限循环(不清楚循环多少次),我们可以把一些特殊函数注册(放置)到这个事件循环上,当满足某些条件的时候,函数就会被循环执行。程序是按照设定的顺序从头执行到尾,运行的次数也是完全按照设定。当在编写异步程序时,必然其中有部分程序的运行耗时是比较久的,需要先让出当前程序的控制权,让其在背后(挂起)运行,让另一部分的程序先运行起来。当背后运行的程序完成后,也需要及时通知主程序已经完成任务可以进行下一步操作,但这个过程所需的时间是不确定的,需要主程序不断的监听状态,一旦收到了任务完成的消息,就开始进行下一步。loop就是这个持续不断的监视器。

    coroutine:中文翻译叫协程,在 Python 中常指代为协程对象类型,我们可以将协程对象注册到事件循环中,
    它会被事件循环调用。我们可以使用 async 关键字来定义一个方法,这个方法在调用时不会立即被执行,
    而是返回一个协程对象。

    task:任务,它是对协程对象的进一步封装,包含了任务的各个状态。

    future:代表将来执行或还没有执行的任务,实际上和 task 没有本质区别。

    另外我们还需要了解 async/await 关键字,它是从 Python 3.6 才出现的,专门用于定义协程。其中,async 定义一个协程,await 用来挂起阻塞方法的执行。

    import asyncio
    async def request(url):
        print('正在请求:',url)
        print('下载成功:',url)
    
    c = request('www.baidu.com')
    
    # 第一步:实例化一个事件循环对象
    loop = asyncio.get_event_loop()
    # 第二步:创建一个任务对象,将协程对象封装到了该对象中
    # task = loop.create_task(c)
    
    # 另一种形式实例化任务对象的方法   
    task = asyncio.ensure_future(c)
    
    #将协程对象注册到事件循环对象中,并且我们需要启动事件循环对象
    loop.run_until_complete(task)
    # 打印task可以看到任务对象状态
    print(task)

    绑定回调函数,在爬虫中必须用回调函数,因为在数据爬取下来后,用回调函数可以进行数据解析

    import asyncio
    
    async def request(url):
        print('正在请求:',url)
        print('下载成功:',url)
        return url
    
    #回调函数必须有一个参数:task
    #task.result():任务对象中封装的协程对象对应的特殊函数内部的返回值
    def callbak(task):
        print('this is callback!')
        print(task.result())
    
    c = request('www.baidu.com')
    
    #给任务对象绑定一个回调函数
    #  创建任务对象
    task = asyncio.ensure_future(c)
    # 绑定回调函数
    task.add_done_callback(callbak)
    
    # 注册到时间循环中
    loop = asyncio.get_event_loop()
    
    loop.run_until_complete(task)

    多任务异步协程

    from time import sleep
    import asyncio
    import time
    urls = ['www.baidu.com','www.sogou.com','www.goubanjia.com']
    start = time.time()
    async def request(url):
        print('正在请求:',url)
        #在多任务异步协程实现中,不可以出现不支持异步的相关代码。
        # sleep(2)
        await asyncio.sleep(2)
        print('下载成功:',url)
    
    loop = asyncio.get_event_loop()
    #任务列表:放置多个任务对象
    tasks = []
    for url in urls:
        c = request(url)
        task = asyncio.ensure_future(c)
        tasks.append(task)
    
    loop.run_until_complete(asyncio.wait(tasks))
    
    print(time.time()-start)

    单线程+多任务异步

    # 面试问题,如何提升爬取效率
    # 使用方向:数据量大,数据占内存大
    #aiohttp:支持异步的一个基于网络请求的模块
    # 和requests模块功能应用都一样,区别就是支持异步
    # pip install aiohttp
    
    import requests
    import asyncio
    import time
    import aiohttp
    #单线程+多任务异步协程
    urls = [
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/tom'
    ]
    # 异步效果,遇到阻塞,挂起阻塞,执行别的任务
    #代理操作:
    #async with await s.get(url,proxy="http://ip:port") as response:
    async def get_pageText(url):
        # 请求对象,with不关闭资源,
       async with aiohttp.ClientSession() as s:
          async with await s.get(url) as response:
              # 拿响应数据有可能阻塞所以需要await, 这里是text方法,request是text方法
               page_text = await response.text()
                # 借助于回调函数进行响应数据的解析操作
               return page_text
    #封装回调函数用于数据解析
    def parse(task):
        #1.获取响应数据
        page_text = task.result()
        print(page_text+',即将进行数据解析!!!')
        #解析操作写在该位置
    
    start = time.time()
    tasks = []
    for url in urls:
        c = get_pageText(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)



  • 相关阅读:
    经过我修改的一个记录集分页插件(C#)[原创]
    基于javascript的asp数据库操作类,含分页、字符串截取、用户登陆验证[原创]
    .net中关于windows身份验证的一个教训[原创]
    IE功能汇总[网上收集]
    一些珍藏代码[网上收集]
    对以前改的c#分页插件的补充[原创]
    ASP验证码图形生成[网上收集]
    关于嵌套使用DataList的心得[原创]
    浏览器标签显式网页logo
    金日开博
  • 原文地址:https://www.cnblogs.com/wmh33/p/11037385.html
Copyright © 2020-2023  润新知