天天看點

02-12 多任務異步協程執行個體

一、注意事項:

'''
1、将多個對象存儲到一個清單中,然後将該清單注冊到事件循環中,
在注冊過程中,該清單需要用wait方法進行處理
2、在任務對象對應的特殊函數内部的實作中,不可以出現不支援異步
子產品的代碼,否則會中斷整個異步效果,并且在該函數的内部中每一
組阻塞操作都必須使用await關鍵字進行修飾
3、requests子產品不支援異步,是以不能出現在async 修飾的函數中
           

二、代碼架構

import time
import asyncio

urls=[
    'http://www.taobao.com',
    'http://www.taobao.com',
    'http://www.taobao.com'
]

async def get_request(url):
    print('正在請求:',url)
    # time.sleep(2) 此時錯誤,因為協程子產品待執行函數中
    # 不允許出現不支援異步子產品的函數,需改為
    # asyncio.sleep(2) 此時雖不會報錯,但還是有問題
    # 阻塞操作必須有await關鍵字修飾,還需修改為

    await asyncio.sleep(2)
    
    print('請求結束:',url)
    return 'xinxin'

tasks=[]

for url in urls:
    c=get_request(url)

    task=asyncio.ensure_future(c)
    tasks.append(task)

loop=asyncio.get_event_loop()
# resp=loop.run_until_complete(tasks) 此時語句是錯誤
# 的,因為loop中注冊的每個任務都是有阻塞的,是以執行過程
# 中必須手動設定挂起操作,即
resp=loop.run_until_complete(asyncio.wait(tasks))



           

三、執行個體應用

import time
import requests
import asyncio
import aiohttp
from lxml import etree

urls=[
    'http://www.taobao.com',
    'http://www.taobao.com',
    'http://www.taobao.com'
]
start_time=time.time()

async def get_request(url):
    # page_text=requests.get(url).text
    #注意,這個請求過程本身就是一個阻塞過程
    # 注意,因為爬蟲最常用的requests子產品,但我們為了
    # 速度,需要學習異步效果,是以說明了requests子產品
    # 不支援異步,是以需改用aiohttp子產品,改寫

    with aiohttp.ClientSession() as s:
        with s.get(url) as resp:
            page_text=resp.text()
            #響應為字元byte時,resp.read()
            return page_text

    #注意,上述隻是主題架構,結果還不能實作異步,需添加細節
    #每一個with前面+async ,在每一步則塞錢加await,即完整代碼


    async with aiohttp.ClientSession() as s:
        async with await s.get(url) as resp:
            page_text = await resp.text()
            # 響應為字元byte時,resp.read()
            return page_text

def parse(task): # 解析函數式就是回調函數
    page_text=tasks.result()   
     #關鍵第一步,将爬取的響應結果取到
    tree=etree.HTML(page_text)
    response=tree.xpath('//p/text()')[0]
    print(response)

if __name__=='__main__' :

    tasks=[]
    for url in urls:
        c=get_request(url)

        task=asyncio.ensure_future(c)
         #發送請求獲得響應
        task.add_done_callback(parse) 
        #解析網頁,實作聚焦爬蟲

        tasks.append(task)
    loop=asyncio.get_event_loop()
    result=loop.run_until_complete(asyncio.wait(tasks))

    print('共計時間為',time.time()-start_time)

           

繼續閱讀