單線程+多任務異步協程: 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修飾的函數,回調函數就是一個普通的函數;