利用協程asyncio爬取搜狗美女圖片(二)——實戰
阿新 • • 發佈:2019-01-01
上節我們詳細的介紹了asyncio庫的應用(連結https://blog.csdn.net/MG1723054/article/details/81778460),本節我們將其應用到實戰之中。主要還是以分析ajax爬取搜狗美女圖片(連結https://blog.csdn.net/MG1723054/article/details/81735834)
直接貼出程式碼,我們在程式碼裡面詳細說明每一行的程式碼含義。
我們以爬取前25個網頁,首先我們再次將之前的沒有新增協程的程式碼放上
# -*- coding: utf-8 -*- """ Spyder Editor This is a NJUer. """ import requests import time from urllib.parse import urlencode #網址編碼 import json #匯入json庫 urls=[] def image_json (url) :###請求庫,利用requests請求構造的連結,然後轉化為json格式,然後得到圖######片的標題和圖片連結。 response=requests.get(url,headers={'User-Agent':'Mozilla/5.0'}) data=json.loads(response.text)['all_items'] for m in range(len(data)) : items={ 'image_url':data[m]['thumbUrl'],'title':data[m]['title'] } yield items def image_download(item):###下載圖片 resource=requests.get(item['image_url']) item['title']=item['title'].replace('|','_') item['title']=item['title'].replace('/','_')###改名,因為有些圖片中有些字元不符合jpg ###圖片命名規範 file='C:\\Users\\FangWei\\Desktop\\網路爬蟲\\爬取酷狗美女圖片\\'+item['title'][0:20]+'.jpg' with open (file,'wb') as f: f.write(resource.content)###將圖片下載,放到指定資料夾 def get_image (offest) : ###get_image函式主要是構造需要的ajax連結 base_url='http://pic.sogou.com/pics/channel/getAllRecomPicByTag.jsp?' data={'category':'美女', 'tag':'全部', 'start':str(offest*15), 'len':'15',} url=base_url+urlencode(data) ###利用urlencode將字典拼接為一個網址連結 return url def main(offest): infor=get_image(offest) #mian函式內部呼叫get_image函式 #time.sleep(1) for item in image_json (infor): image_download(item) if __name__=='__main__' : start=time.time() for x in range(1,26): #設定爬取變數,設定30,根據上面分析表示可以爬取30*15張圖片 offest=x main(offest) #呼叫主函式main() end=time.time() times=end-start print(times)
執行時間為:
可以看到,爬取完這些網頁所消耗的時間還是比較多的
下面,我們將該程式修改,使其變為單執行緒協程併發,以此來提高效率。
# -*- coding: utf-8 -*- """ Spyder Editor This is a NJUer. """ import requests import time ,json from urllib.parse import urlencode import asyncio,aiohttp urls=[] def image_json (url) : response=requests.get(url,headers={'User-Agent':'Mozilla/5.0'}) data=json.loads(response.text)['all_items'] for m in range(len(data)) : items={ 'image_url':data[m]['thumbUrl'],'title':data[m]['title'] } yield items ##利用生成器,與return類似,但是yield可節省記憶體,實際上yield也可作協程 async def image_download(item): item['title']=item['title'].replace('|','_') item['title']=item['title'].replace('/','_')###資料命名處理,在爬取中發現有的字元不符合jpg命名規範 file='C:\\Users\\FangWei\\Desktop\\網路爬蟲\\爬取搜狗美女圖\\'+item['title'][0:20]+'.jpg'####命名檔名 async with aiohttp.ClientSession() as session: async with session.get(item['image_url']) as resp:###aiohttp模組中ClientSession方法,這兩句方法最穩妥,也有session=aiohttp.ClientSession(),resp=session.get(item['image_url']),但是可能會報錯,如果不報錯,可以使用這種方法,報錯就使用上面的程式碼 #print(resp.status) imgcode=await resp.read()####讀取二進位制檔案,這與requests庫不同,requests讀######取二進位制的方法是content with open(file,'wb')as f: f.write(imgcode) ####將二進位制檔案寫入檔案 def get_image (offest) : base_url='http://pic.sogou.com/pics/channel/getAllRecomPicByTag.jsp?' data={'category':'美女', 'tag':'全部', 'start':str(offest*15), 'len':'15',} url=base_url+urlencode(data) return url def main(offest): infor=get_image(offest) #time.sleep(1) #for item in image_json (infor): #image_download(item) tasks=[asyncio.ensure_future(image_download(item)) for item in image_json (infor) ] ###開啟協程多工佇列,該語句是列表推導式,列表的簡寫,與上面兩句等效,但是該句是利用協程,多個佇列一起進行 loop=asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks))###將任務註冊到事件迴圈,並啟動任務 if __name__=='__main__' : start=time.time() for x in range(1,26): offest=x main(offest) end=time.time() times=end-start print(times)
上面的程式碼執行結束,執行時間為:
我們可以明顯的看到,通過協程併發我們執行時間縮短了一半多,所以我們在實際爬取過程中可以適當的使用協程。
原創不易,如需轉載,請註明出處和作者,謝謝。