音效素材网提供各类素材,打造精品素材网站!

站内导航 站长工具 投稿中心 手机访问

音效素材

python 基于AioHttp 异步抓取火星图片
日期:2021-09-08 13:48:42   来源:脚本之家

翻译:大江狗

原文链接:https://pfertyk.me/2017/06/getting-mars-photos-from-nasa-using-aiohttp/

小编注:aiohttp是基于asyncio实现的异步http框架。

本文案例也可以使用异步django实现。

我是Andy Weir写的《火星人》一书的忠实粉丝。阅读时,我想知道马克·沃特尼(Mark Watney)绕着红色星球走的感觉如何。最近,多亏了 Twilio的这篇博文, 我发现NASA提供了一个公共API,可以提供火星漫游者拍摄的照片。但是,由于不是MMS的忠实拥护者,我决定编写自己的应用程序,以将具有启发性的图像直接传递到我的浏览器中。

创建aiohttp应用程序

让我们从一个简单的应用程序开始,只是为了启动和运行aiohttp。首先,创建一个新的virtualenv。建议使用Python 3.5以后版本,因为我们将使用asyncio提供的async def和await语法。如果您想进一步开发该项目并利用异步理解的优势,则可以使用Python 3.6(本例使用python版本)。接下来,安装aiohttp:

pip install aiohttp

现在创建一个python文件(称为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,则可能需要说明以下几点:

  • get_mars_photo协程是一个请求处理程序;它以HTTP请求作为唯一参数,并负责返回HTTP响应(或引发异常)
  • app是高级服务器;它支持路由器,中间件和信号(对于该程序,我们将仅使用路由器)
  • app.router.add_get 在HTTP GET方法和'/'路径上注册请求处理程序

注意:请求处理程序不必一定是协程,它们可以是常规函数。但是我们将使用asyncio的功能,因此程序中的大多数函数都将使用进行定义async def。

运行应用程序

要运行您的应用程序,您可以在文件末尾添加以下行:

web.run_app(app, host='127.0.0.1', port=8080)

然后像运行其他任何Python脚本一样运行它:

python nasa.py

但是有更好的方法。在许多第三方库中,您可以找到aiohttp-devtools。它提供了一个很好的runserver命令,可以自动检测您的应用并支持实时重载:

pip install aiohttp-devtools
adev runserver -p 8080 nasa.py

现在如果您访问localhost:8080,则应该在浏览器中看到"A photo of mars"的字样。

使用NASA API

当然,这还没有结束。如果您是一位敏锐的观察者,您会注意到我们没有得到实际的图像,而是一些文本。现在让我们解决这个问题。

要从火星获取照片,我们将使用NASA API。每个火星探路者(rover)都有自己的URL(对于好奇号,它url是https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos)。我们必须为每个请求至少提供2个参数:

  • sol:火星轮转或拍摄照片的日期,从探路者的着陆日期开始算起(最大值可以rover/max_sol在响应的一部分中找到 )
  • API_KEY:由美国航天局提供的API密钥(你可以使用默认的:DEMO_KEY)

响应数据里我们将获得一张照片列表,每张照片均带有URL,相机信息和探路者信息。

修改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)

到底发生了什么事?

  • 我们选择一个随机拍摄日期(对于“好奇心” max_sol,在撰写本文时,其值为1722)
  • ClientSession 创建一个会话,我们可以使用该会话从NASA API获取响应
  • 我们使用获取JSON响应 resp.json()
  • 我们检查响应中是否存在“照片”键;如果没有,我们已经达到了每小时请求数量的上限,我们需要稍等片刻
  • 如果当天没有照片,我们会再次检查是否有其他拍摄时间
  • 然后,我们使用HTTPFound响应重定向到找到的照片

获取NASA API密钥

DEMO_KEYNASA提供的默认设置可以正常工作,但是您很快就会达到每小时API调用的限制。我建议您获取自己的API密钥。您可以在此处进行操作 (注册过程非常简单快捷)。

现在,当您运行该应用程序时,您将直接从火星重定向到一个漂亮的图像:

好吧,这不完全是我的意思...

验证图像

您刚刚看到的图像并不让人受到启发。事实证明,漫游者拍摄了很多非常无聊的照片。我想看看马克·沃特尼(Mark Watney)在他不可思议的旅程中所看到的,但这还不够好。让我们找到一种解决方法。

我们将需要对图像进行某种形式的验证。在指定筛选条件前,我们可以修改代码:

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')

这里发生了一些新的事情:

  • 我们使用先前定义的函数获取URL,然后使用读取图像中的原始字节 resp.read()
  • 我们检查我们的图片是否足够好;如果没有,我们一直在寻找
  • 一旦有了令人满意的照片,我们会将其放入响应中(注意,我们仍然使用与web.Response以前相同的照片,但是这次我们指定body 而不是text,同时了定义content_type

注意:在此代码中,我们删除了重定向(HTTPFound),因此现在我们可以轻松地刷新页面以获取另一个图像。

现在我们需要弄清楚如何验证照片。我们可以很容易做到的一件事就是检查图像尺寸否足够大。这不是一个完美的验证,但现在应该这样做。要处理图像,我们将需要python的图片库Pillow。

pip install pillow

我们的验证函数可能如下所示:

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

现在刷新浏览器,应该可以看到火星大图了。

现在我们可以更进一步,拒绝灰度图像:

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'

现在我们的程序开始返回更多鼓舞人心的照片:

偶尔还能看到机器人自拍:

总结

我们整个程序如下所示:

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中获取价值,传递流动站的名称,缓存URL),但是现在它已经完成了工作:我们可以得到一张随机的,鼓舞人心的火星照片,并觉得我们确实在那里。

我希望您喜欢这个简短的教程。如果您发现错误或有任何疑问,请告诉我。

以上就是python 基于AioHttp 异步抓取火星图片的详细内容,更多关于python AioHttp 抓取火星图片的资料请关注其它相关文章!

    您感兴趣的教程

    在docker中安装mysql详解

    本篇文章主要介绍了在docker中安装mysql详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编...

    详解 安装 docker mysql

    win10中文输入法仅在桌面显示怎么办?

    win10中文输入法仅在桌面显示怎么办?

    win10系统使用搜狗,QQ输入法只有在显示桌面的时候才出来,在使用其他程序输入框里面却只能输入字母数字,win10中...

    win10 中文输入法

    一分钟掌握linux系统目录结构

    这篇文章主要介绍了linux系统目录结构,通过结构图和多张表格了解linux系统目录结构,感兴趣的小伙伴们可以参考一...

    结构 目录 系统 linux

    PHP程序员玩转Linux系列 Linux和Windows安装

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,Linux和Windows安装nginx教程,具有一定的参考价值,感兴趣...

    玩转 程序员 安装 系列 PHP

    win10怎么安装杜比音效Doby V4.1 win10安装杜

    第四代杜比®家庭影院®技术包含了一整套协同工作的技术,让PC 发出清晰的环绕声同时第四代杜比家庭影院技术...

    win10杜比音效

    纯CSS实现iOS风格打开关闭选择框功能

    这篇文章主要介绍了纯CSS实现iOS风格打开关闭选择框,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作...

    css ios c

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的

    Win7给电脑C盘扩容的办法大家知道吗?当系统分区C盘空间不足时,就需要给它扩容了,如果不管,C盘没有足够的空间...

    Win7 C盘 扩容

    百度推广竞品词的投放策略

    SEM是基于关键词搜索的营销活动。作为推广人员,我们所做的工作,就是打理成千上万的关键词,关注它们的质量度...

    百度推广 竞品词

    Visual Studio Code(vscode) git的使用教程

    这篇文章主要介绍了详解Visual Studio Code(vscode) git的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    教程 Studio Visual Code git

    七牛云储存创始人分享七牛的创立故事与

    这篇文章主要介绍了七牛云储存创始人分享七牛的创立故事与对Go语言的应用,七牛选用Go语言这门新兴的编程语言进行...

    七牛 Go语言

    Win10预览版Mobile 10547即将发布 9月19日上午

    微软副总裁Gabriel Aul的Twitter透露了 Win10 Mobile预览版10536即将发布,他表示该版本已进入内部慢速版阶段,发布时间目...

    Win10 预览版

    HTML标签meta总结,HTML5 head meta 属性整理

    移动前端开发中添加一些webkit专属的HTML5头部标签,帮助浏览器更好解析HTML代码,更好地将移动web前端页面表现出来...

    移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家...

    移动端 html5 长按

    HTML常用meta大全(推荐)

    这篇文章主要介绍了HTML常用meta大全(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    cdr怎么把图片转换成位图? cdr图片转换为位图的教程

    cdr怎么把图片转换成位图? cdr图片转换为

    cdr怎么把图片转换成位图?cdr中插入的图片想要转换成位图,该怎么转换呢?下面我们就来看看cdr图片转换为位图的...

    cdr 图片 位图

    win10系统怎么录屏?win10系统自带录屏详细教程

    win10系统怎么录屏?win10系统自带录屏详细

    当我们是使用win10系统的时候,想要录制电脑上的画面,这时候有人会想到下个第三方软件,其实可以用电脑上的自带...

    win10 系统自带录屏 详细教程

    + 更多教程 +
    ASP编程JSP编程PHP编程.NET编程python编程