一、注意事項:
'''
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)