zoukankan      html  css  js  c++  java
  • 爬虫第四章 单线程+多任务异步协程

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

    事件循环 loop: 无限循环的对象,事件循环中最终需要将一些特殊的函数注册到该事件循环中
    
         特殊的函数: 被ansyc关键字修饰的函数
    
    协程: 本质上是一个对象,可以把协程对象注册到事件循环中,
    
    任务对象:就是对协程对象进一步的封装.
    
    绑定回调函数(即在执行完特殊函数之后执行这个回调函数):task.add_done_callback(func)
    
      - func(task) :task 参数表示的就是绑定的任务对象
    
        - task.result()  返回的就是任务对象对应的特殊函数内部的返回值
    
        - 回调函数 多被用作爬虫的解析方法(就是标签定位和解析数据)
    
    await: 在执行任务函数的时候,如果出现了阻塞,则必须在前面加一个await进行修饰

    异步操作的体现:

      当将多个协程对象注册到事件循环中后,事件循环开启时,则会循环执行其内部的协程对象.

      假如事件循环对象在执行某一个协程对象时,发生了阻塞,则事件循环会执行下一个协程对象

    aiohttp模块: 支持异步的网络请求模块  查看中文文档 点击这里

    环境安装: aiohttp
    如何进行UA伪装:
        session.get(url=url,headers=headers)
    参数的伪装:
        session.get(url=url ,headers=headers ,data/params)
    代理ip:
        session.get(url=url,headers=headers,proxy='http://代理ip:代理端口')

     实例 : 爬取喜马拉雅郭德纲的相声

    import requests 
    import asyncio
    import aiphttp

    url = 'https://www.ximalaya.com/revision/play/album?albumId=19366477&pageNum=1&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'
        }

    url_list=[]

    #从url中获取到每一个音频文件的数据(这里我们要将这个协程对象包装成任务对象)
    async def get_audio_data(url):
      #这里的这个aiphttp.ClientSession()就相当于实例化一个requests对象(可以发送网络请求的对象)
      async with aiphttp.ClientSession() as session:
        #通过这个session对象发送get请求获取到响应数据
        async with await session.get(url=url,headers=headers) as response:
          #将响应数据的格式转化为2进制流的形式
          audio_data=await response.read() # read是aiphttp中获取2进制流的方法
          return {'data':audio_data,'url':url} 

    def save_data(task):
      audio_data = task.result()
      name = audio_data['url'].split('/')[-1]
      data = audio_data['data']
      with open(name,'wb') as fp:
        fp.write(data)
      print(name,'下载成功!!')

    page_text = requests.get(url=url,headers=headers).json()
    #从页面数据中找到所有的url,并将它们添加到url_list中
    for dic in page_text['data']['trackAudioPlay']:
      audio_url=dic['src']
      url_list.append(audio_url)

    task_list = []
    for url in url_list:
      #创建协程对象
      audio_data = get_audio_data(url)
      #将协程对象包装成任务对象
      task = asyncio.ensure_future(audio_data)
      #绑定回调函数
      async.add_done_callback(save_data)
      #这里我们添加到列表中是为了下面的异步执行任务对象做准备
      task_list.append(task)

    #创建事件循环对象
    loop = asyncio.get_event_loop()
    #将任务对象列表放到事件循环中,实现异步效果(将任务对象注册到事件循环中,并执行事件循环)
    loop.run_until_complate(asyncio.wait(tasks))


    执行步骤:

           先从大的url中获取到每一个音频的url,将他们添加到一个列表中,然后逐个对这个列表发送请求,获取到每一个页面数据,
    通过解析获取到音频的数据,然后创建协程对象,将协程对象包装成任务对象(async),然后给每一个任务对象添加回调函数(在这里回调函数的作用就是保存数据),
    然后将所有的任务对象都添加到一个列表中,然后创建事件循环对象(asyncio.get_event_loop()),将之前弄好的那个任务对象列表放到这个事件循环对象中(loop.run_util_complate()),就实现了异步执行的效果.

     这里总结一下这里的注意事项:

    在封装任务对象的时候,前面加上async 就行,但是要注意,函数内部不允许出现不支持异步代码的模块,还有函数内部中的所有阻塞操作必须使用await进行修饰;
    requests模块就是不支持异步代码的模块,解决方法就是使用支持异步代码的模块(aiohttp模块);
    任务对象就是用async修饰的函数,回调函数就是一个普通的函数;

      

  • 相关阅读:
    Jenkins配置:添加用户和管理权限
    Jenkins安装与配置
    jenkins配置邮件通知
    Jenkins 配置邮件通知
    jenkins+SVN配置
    第九周学习进度
    梦断代码阅读笔记 01
    第八周学习进度
    “理了么”软件特点NABCD个人分析
    第七周学习进度
  • 原文地址:https://www.cnblogs.com/zty1304368100/p/11025262.html
Copyright © 2011-2022 走看看