爬蟲第四章 單線程+多任務異步協程

單線程+多任務異步協程: asynciojson

事件循環 loop: 無限循環的對象,事件循環中最終須要將一些特殊的函數註冊到該事件循環中

     特殊的函數: 被ansyc關鍵字修飾的函數

協程: 本質上是一個對象,能夠把協程對象註冊到事件循環中,

任務對象:就是對協程對象進一步的封裝.

綁定回調函數(即在執行完特殊函數以後執行這個回調函數):task.add_done_callback(func)

  - func(task) :task 參數表示的就是綁定的任務對象

    - task.result()  返回的就是任務對象對應的特殊函數內部的返回值

    - 回調函數 多被用做爬蟲的解析方法(就是標籤訂位和解析數據)

await: 在執行任務函數的時候,若是出現了阻塞,則必須在前面加一個await進行修飾

異步操做的體現:網絡

  當將多個協程對象註冊到事件循環中後,事件循環開啓時,則會循環執行其內部的協程對象.session

  假如事件循環對象在執行某一個協程對象時,發生了阻塞,則事件循環會執行下一個協程對象app

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:代理端口')

 實例 : 爬取喜馬拉雅郭德綱的相聲async

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()),就實現了異步執行的效果.

 這裏總結一下這裏的注意事項:oop

在封裝任務對象的時候,前面加上async 就行,可是要注意,函數內部不容許出現不支持異步代碼的模塊,還有函數內部中的全部阻塞操做必須使用await進行修飾;requests模塊就是不支持異步代碼的模塊,解決方法就是使用支持異步代碼的模塊(aiohttp模塊);任務對象就是用async修飾的函數,回調函數就是一個普通的函數;
相關文章
相關標籤/搜索