python使用非同步每秒鐘就能下載一張高清大圖,快不快?

sergiojune發表於2019-03-03

不知道上篇文章大家學得怎樣了,因為這篇文章是利用aiohttp這個庫來進行說明的。如果還沒有很明白或者還沒有看過的話可以去多看看爬蟲速度太慢?來試試用非同步協程提速吧!這篇文章,看完之後記得多加練習哈,這樣才能掌握。

如果爬蟲需要展現速度,我覺得就是去下載圖片吧,原本是想選擇去煎蛋那裡下載圖片的,那裡的美女圖片都是高質量的,我稿子都是差不多寫好了的,無奈今天重新看下,妹子圖的入口給關了,至於為什麼關呢,大家可以去看看昨天好奇心日報的關停原因吧或者百度下,這裡就不多說了,這次我選擇了去下載無版權高清圖片,因為做自媒體的人很怕侵權,找無版權的圖片彷彿成了日常工作,所以這次我選擇了這個網站

https://unsplash.com/

python使用非同步每秒鐘就能下載一張高清大圖,快不快?

那下面來看看使用非同步以及不使用非同步的差別?

python使用非同步每秒鐘就能下載一張高清大圖,快不快?

(右邊是使用非同步的,左邊是沒有使用非同步的,由於用於測試,所以選擇下載12張圖片即可)

可以看到,在使用非同步之後執行的時間比不使用非同步的程式少了差不多6倍的時間,是不是感覺到high了起來?那我們分析下怎樣爬取吧。

1.找目標網頁

這個網站首頁就有一堆圖片,而且往下拉時還會自動重新整理,很明顯是個ajax載入,但不怕,動態載入這東西我們之前講過了,所以開啟開發者工具看下是怎樣的請求吧。

python使用非同步每秒鐘就能下載一張高清大圖,快不快?

python使用非同步每秒鐘就能下載一張高清大圖,快不快?

往下拉的時候很容易看到這個請求,這個是一個get請求,狀態碼為200,網址為https://unsplash.com/napi/photos?page=3&per_page=12&order_by=latest,有三個引數,很容易知道page引數就是頁,這個引數是變化的,其他的引數都是不變的。

python使用非同步每秒鐘就能下載一張高清大圖,快不快?

返回來的內容是個json型別,裡面的links下的download就是我們圖片下載的連結,現在所有東西都清楚了,那下面就是程式碼了。

2.程式碼部分

async def __get_content(self, link):
       async with aiohttp.ClientSession() as session:
           response = await session.get(link)
           content = await response.read()
           return content複製程式碼

這個是獲取圖片的內容的方法,aiohttpClientSession和requests.session的用法是差不多,只不過獲取unicode編碼的方法變成了read()

下面是完整程式碼

import requests, os, time
import aiohttp, asyncio

class Spider(object):
   def __init__(self):
       self.headers = {
           'User-Agent''Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
       self.num = 1
       if '圖片' not in os.listdir('.'):
           os.mkdir('圖片')
       self.path = os.path.join(os.path.abspath('.'), '圖片')
       os.chdir(self.path)  # 進入檔案下載路徑

   async def __get_content(self, link):
       async with aiohttp.ClientSession() as session:
           response = await session.get(link)
           content = await response.read()
           return content

   def __get_img_links(self, page):
       url = 'https://unsplash.com/napi/photos'
       data = {
           'page': page,
           'per_page'12,
           'order_by''latest'
       }
       response = requests.get(url, params=data)
       if response.status_code == 200:
           return response.json()
       else:
           print('請求失敗,狀態碼為%s' % response.status_code)

   async def __download_img(self, img):
       content = await self.__get_content(img[1])
       with open(img[0]+'.jpg''wb'as f:
           f.write(content)
       print('下載第%s張圖片成功' % self.num)
       self.num += 1

   def run(self):
       start = time.time()
       for x in range(1101):  # 下載一百頁的圖片就可以了,或者自己更改頁數
           links = self.__get_img_links(x)
           tasks = [asyncio.ensure_future(self.__download_img((link['id'], link['links']['download']))) for link in links]
           loop = asyncio.get_event_loop()
           loop.run_until_complete(asyncio.wait(tasks))
           if self.num >= 10:  # 測試速度使用,如需要下載多張圖片可以註釋這段程式碼
               break
       end = time.time()
       print('共執行了%s秒' % (end-start))

def main():
   spider = Spider()
   spider.run()

if __name__ == '__main__':
   main()複製程式碼

可以看到不到50行的程式碼就可以把整個網網站的圖片下載下來了,不得不吹一下python的強大~~~

寫在最後

爬取煎蛋妹子圖片的程式我寫好了,如果大家需要的話,可以去公眾號日常學python找我要,只限前40名哈!!!給你看個效果先!

python使用非同步每秒鐘就能下載一張高清大圖,快不快?

大家有什麼不太明白的話可以在下方留言哈。如果文章對你有用的話,歡迎轉發點贊讓更多的人知道。

python使用非同步每秒鐘就能下載一張高清大圖,快不快?

日常學python

程式碼不止bug,還有美和樂趣


相關文章