翻譯:大江狗
原文鏈接:https://pfertyk.me/2017/06/getting-mars-photos-from-nasa-using-aiohttp/
小編注:aiohttp是基于asyncio實(shí)現(xiàn)的異步http框架。
本文案例也可以使用異步django實(shí)現(xiàn)。
我是Andy Weir寫(xiě)的《火星人》一書(shū)的忠實(shí)粉絲。閱讀時(shí),我想知道馬克·沃特尼(Mark Watney)繞著紅色星球走的感覺(jué)如何。最近,多虧了 Twilio的這篇博文, 我發(fā)現(xiàn)NASA提供了一個(gè)公共API,可以提供火星漫游者拍攝的照片。但是,由于不是MMS的忠實(shí)擁護(hù)者,我決定編寫(xiě)自己的應(yīng)用程序,以將具有啟發(fā)性的圖像直接傳遞到我的瀏覽器中。
讓我們從一個(gè)簡(jiǎn)單的應(yīng)用程序開(kāi)始,只是為了啟動(dòng)和運(yùn)行aiohttp。首先,創(chuàng)建一個(gè)新的virtualenv。建議使用Python 3.5以后版本,因?yàn)槲覀儗⑹褂胊syncio提供的async def和await語(yǔ)法。如果您想進(jìn)一步開(kāi)發(fā)該項(xiàng)目并利用異步理解的優(yōu)勢(shì),則可以使用Python 3.6(本例使用python版本)。接下來(lái),安裝aiohttp:
pip install aiohttp
現(xiàn)在創(chuàng)建一個(gè)python文件(稱(chēng)為nasa.py),并將一些代碼放入其中:
from aiohttp import web async def get_mars_photo(request): return web.Response(text='A photo of Mars') app = web.Application() app.router.add_get('/', get_mars_photo, name='mars_photo')
如果您不熟悉aiohttp,則可能需要說(shuō)明以下幾點(diǎn):
注意:請(qǐng)求處理程序不必一定是協(xié)程,它們可以是常規(guī)函數(shù)。但是我們將使用asyncio的功能,因此程序中的大多數(shù)函數(shù)都將使用進(jìn)行定義async def。
要運(yùn)行您的應(yīng)用程序,您可以在文件末尾添加以下行:
web.run_app(app, host='127.0.0.1', port=8080)
然后像運(yùn)行其他任何Python腳本一樣運(yùn)行它:
python nasa.py
但是有更好的方法。在許多第三方庫(kù)中,您可以找到aiohttp-devtools。它提供了一個(gè)很好的runserver命令,可以自動(dòng)檢測(cè)您的應(yīng)用并支持實(shí)時(shí)重載:
pip install aiohttp-devtools adev runserver -p 8080 nasa.py
現(xiàn)在如果您訪(fǎng)問(wèn)localhost:8080,則應(yīng)該在瀏覽器中看到"A photo of mars"的字樣。
當(dāng)然,這還沒(méi)有結(jié)束。如果您是一位敏銳的觀(guān)察者,您會(huì)注意到我們沒(méi)有得到實(shí)際的圖像,而是一些文本?,F(xiàn)在讓我們解決這個(gè)問(wèn)題。
要從火星獲取照片,我們將使用NASA API。每個(gè)火星探路者(rover)都有自己的URL(對(duì)于好奇號(hào),它url是https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos)。我們必須為每個(gè)請(qǐng)求至少提供2個(gè)參數(shù):
響應(yīng)數(shù)據(jù)里我們將獲得一張照片列表,每張照片均帶有URL,相機(jī)信息和探路者信息。
修改nasa.py文件,如下所示:
import random from aiohttp import web, ClientSession from aiohttp.web import HTTPFound NASA_API_KEY = 'DEMO_KEY' ROVER_URL = 'https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos' async def get_mars_image_url_from_nasa(): while True: sol = random.randint(0, 1722) params = {'sol': sol, 'api_key': NASA_API_KEY} async with ClientSession() as session: async with session.get(ROVER_URL, params=params) as resp: resp_dict = await resp.json() if 'photos' not in resp_dict: raise Exception photos = resp_dict['photos'] if not photos: continue return random.choice(photos)['img_src'] async def get_mars_photo(request): url = await get_mars_image_url_from_nasa() return HTTPFound(url)
到底發(fā)生了什么事?
DEMO_KEYNASA提供的默認(rèn)設(shè)置可以正常工作,但是您很快就會(huì)達(dá)到每小時(shí)API調(diào)用的限制。我建議您獲取自己的API密鑰。您可以在此處進(jìn)行操作 (注冊(cè)過(guò)程非常簡(jiǎn)單快捷)。
現(xiàn)在,當(dāng)您運(yùn)行該應(yīng)用程序時(shí),您將直接從火星重定向到一個(gè)漂亮的圖像:
好吧,這不完全是我的意思...
您剛剛看到的圖像并不讓人受到啟發(fā)。事實(shí)證明,漫游者拍攝了很多非常無(wú)聊的照片。我想看看馬克·沃特尼(Mark Watney)在他不可思議的旅程中所看到的,但這還不夠好。讓我們找到一種解決方法。
我們將需要對(duì)圖像進(jìn)行某種形式的驗(yàn)證。在指定篩選條件前,我們可以修改代碼:
async def get_mars_photo_bytes(): while True: image_url = await get_mars_image_url_from_nasa() async with ClientSession() as session: async with session.get(image_url) as resp: image_bytes = await resp.read() if await validate_image(image_bytes): break return image_bytes async def get_mars_photo(request): image = await get_mars_photo_bytes() return web.Response(body=image, content_type='image/jpeg')
這里發(fā)生了一些新的事情:
注意:在此代碼中,我們刪除了重定向(HTTPFound),因此現(xiàn)在我們可以輕松地刷新頁(yè)面以獲取另一個(gè)圖像。
現(xiàn)在我們需要弄清楚如何驗(yàn)證照片。我們可以很容易做到的一件事就是檢查圖像尺寸否足夠大。這不是一個(gè)完美的驗(yàn)證,但現(xiàn)在應(yīng)該這樣做。要處理圖像,我們將需要python的圖片庫(kù)Pillow。
pip install pillow
我們的驗(yàn)證函數(shù)可能如下所示:
import io from PIL import Image async def validate_image(image_bytes): image = Image.open(io.BytesIO(image_bytes)) return image.width >= 1024 and image.height >= 1024
現(xiàn)在刷新瀏覽器,應(yīng)該可以看到火星大圖了。
現(xiàn)在我們可以更進(jìn)一步,拒絕灰度圖像:
async def validate_image(image_bytes): image = Image.open(io.BytesIO(image_bytes)) return image.width >= 1024 and image.height >= 1024 and image.mode != 'L'
現(xiàn)在我們的程序開(kāi)始返回更多鼓舞人心的照片:
偶爾還能看到機(jī)器人自拍:
我們整個(gè)程序如下所示:
import random import io from aiohttp import web, ClientSession from PIL import Image NASA_API_KEY = 'DEMO_KEY' ROVER_URL = 'https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos' async def validate_image(image_bytes): image = Image.open(io.BytesIO(image_bytes)) return image.width >= 1024 and image.height >= 1024 and image.mode != 'L' async def get_mars_image_url_from_nasa(): while True: sol = random.randint(0, 1722) params = {'sol': sol, 'api_key': NASA_API_KEY} async with ClientSession() as session: async with session.get(ROVER_URL, params=params) as resp: resp_dict = await resp.json() if 'photos' not in resp_dict: raise Exception photos = resp_dict['photos'] if not photos: continue return random.choice(photos)['img_src'] async def get_mars_photo_bytes(): while True: image_url = await get_mars_image_url_from_nasa() async with ClientSession() as session: async with session.get(image_url) as resp: image_bytes = await resp.read() if await validate_image(image_bytes): break return image_bytes async def get_mars_photo(request): image = await get_mars_photo_bytes() return web.Response(body=image, content_type='image/jpeg') app = web.Application() app.router.add_get('/', get_mars_photo, name='mars_photo')
我們還可以改善很多事情(例如max_sol從API中獲取價(jià)值,傳遞流動(dòng)站的名稱(chēng),緩存URL),但是現(xiàn)在它已經(jīng)完成了工作:我們可以得到一張隨機(jī)的,鼓舞人心的火星照片,并覺(jué)得我們確實(shí)在那里。
我希望您喜歡這個(gè)簡(jiǎn)短的教程。如果您發(fā)現(xiàn)錯(cuò)誤或有任何疑問(wèn),請(qǐng)告訴我。
以上就是python 基于AioHttp 異步抓取火星圖片的詳細(xì)內(nèi)容,更多關(guān)于python AioHttp 抓取火星圖片的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
標(biāo)簽:興安盟 黔東 亳州 拉薩 廊坊 渭南 內(nèi)江 綿陽(yáng)
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《python 基于AioHttp 異步抓取火星圖片》,本文關(guān)鍵詞 python,基于,AioHttp,異步,抓取,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。