Как получить данные из HTTP API с помощью Python?

начало работы с массивами Python Программирование и разработка

Большую часть времени при работе со сторонними данными мы будем обращаться к HTTP API. То есть мы будем делать HTTP-запрос к веб-странице, предназначенной для чтения машинами, а не людьми. Данные API обычно представлены в машиночитаемом формате — обычно JSON или XML. (Если мы столкнемся с данными в другом формате, мы, конечно, можем использовать методы, описанные в других местах этой книги, для преобразования их в JSON!) Давайте посмотрим, как использовать HTTP API из Python.

Общие принципы использования HTTP API просты:

  1. Выполните HTTP-вызов URL-адресов для API, возможно, включая некоторые данные аутентификации (например, ключ API), чтобы показать, что мы авторизованы.
  2. Верните данные.
  3. Сделайте с ним что-нибудь полезное.

Python предоставляет достаточно функциональности в своей стандартной библиотеке, чтобы делать все это без каких-либо дополнительных модулей, но это значительно облегчит нам жизнь, если мы возьмем пару сторонних модулей, чтобы сгладить процесс. Первый — это модуль запросов. Это HTTP-библиотека для Python, которая делает получение данных HTTP более приятным, чем встроенная библиотека Python urllib.request, и ее можно установить с помощью python -m pip install requests.

Чтобы показать, насколько легко им пользоваться, мы воспользуемся API Pixabay (задокументировано здесь ). Pixabay — это сайт стоковых фотографий, где все изображения доступны для повторного использования, что делает его очень удобным местом назначения. Здесь мы сосредоточимся на фруктах. Мы будем использовать изображения фруктов, которые мы соберем позже, при работе с файлами, но сейчас мы просто хотим найти изображения фруктов, потому что это вкусно и полезно для нас.

Для начала мы кратко рассмотрим, какие изображения доступны на Pixabay. Мы возьмем сотню изображений, быстро просмотрим их и выберем нужные. Для этого нам понадобится ключ API Pixabay, поэтому нам нужно создать учетную запись, а затем получить ключ, указанный в документации API в разделе «Поиск изображений».

Модуль запросов

Базовая версия создания HTTP-запроса к API с помощью requestsмодуля включает создание URL-адреса HTTP, его запрос и последующее чтение ответа. Здесь этот ответ в формате JSON. Модуль requestsупрощает каждый из этих шагов. Параметры API представляют собой словарь Python, get()функция выполняет вызов, и если API возвращает JSON, requestsделает его доступным, как.jsonв ответе. Таким образом, простой вызов будет выглядеть так:

import requests

PIXABAY_API_KEY = "11111111-7777777777777777777777777"

base_url = "https://pixabay.com/api/"
base_params = {
    "key": PIXABAY_API_KEY,
    "q": "fruit",
    "image_type": "photo",
    "category": "food",
    "safesearch": "true"
}

response = requests.get(base_url, params=base_params)
results = response.json()
>>> print(len(results["hits"]))
20
>>> print(results["hits"][0])
{'id': 2277, 'pageURL': 'https://pixabay.com/photos/berries-fruits-food-blackberries-2277/', 'type': 'photo', 'tags': 'berries, fruits, food', 'previewURL': 'https://cdn.pixabay.com/photo/2010/12/13/10/05/berries-2277_150.jpg', 'previewWidth': 150, 'previewHeight': 99, 'webformatURL': 'https://pixabay.com/get/gc9525ea83e582978168fc0a7d4f83cebb500c652bd3bbe1607f98ffa6b2a15c70b6b116b234182ba7d81d95a39897605_640.jpg', 'webformatWidth': 640, 'webformatHeight': 426, 'largeImageURL': 'https://pixabay.com/get/g26eb27097e94a701c0569f1f77ef3975cf49af8f47e862d3e048ff2ba0e5e1c2e30fadd7a01cf2de605ab8e82f5e68ad_1280.jpg', 'imageWidth': 4752, 'imageHeight': 3168, 'imageSize': 2113812, 'views': 866775, 'downloads': 445664, 'collections': 1688, 'likes': 1795, 'comments': 366, 'user_id': 14, 'user': 'PublicDomainPictures', 'userImageURL': 'https://cdn.pixabay.com/user/2012/03/08/00-13-48-597_250x250.jpg'}

API возвращает 20 обращений на страницу, а нам нужна сотня результатов. Для этого мы добавляем pageпараметр в наш список params. Тем не менее, мы не хотим изменять наш base_paramsкаждый раз, поэтому способ приблизиться к этому — создать цикл, а затем сделать копию дляbase_params каждого запроса. Встроенный copyмодуль делает именно это, поэтому мы можем вызывать API пять раз в цикле:

for page in range(1, 6):
    this_params = copy.copy(base_params)
    this_params["page"] = page
    response = requests.get(base_url, params=params)

Это сделает пять отдельных запросов к API, один с page=1, следующий с page=2и так далее, получая разные наборы результатов изображения при каждом вызове. Это удобный способ просмотреть большой набор результатов API. Большинство API реализуют разбиение на страницы, когда один вызов API возвращает только ограниченный набор результатов. Затем мы запрашиваем дополнительные страницы с результатами — так же, как просматриваем результаты запроса из поисковой системы.

Читайте также:  Java или JavaScript: тщательное сравнение

Поскольку нам нужна сотня результатов, мы могли бы просто решить, что это пять вызовов по 20 результатов каждый, но было бы более надежным продолжать запрашивать страницы до тех пор, пока мы не получим сотню результатов, которые нам нужны, а затем остановиться. Это защищает вызовы в случае, если Pixabay изменит количество результатов по умолчанию на 15 или подобное. Это также позволяет нам справляться с ситуацией, когда для наших условий поиска нет сотни изображений. Таким образом, у нас есть whileцикл и каждый раз увеличивается номер страницы, а затем, если мы достигли 100 изображений или если нет изображений для извлечения, мы выходим из цикла:

images = []
page = 1
while len(images) < 100:
    this_params = copy.copy(base_params)
    this_params["page"] = page
    response = requests.get(base_url, params=this_params)
    if not response.json()["hits"]: break
    for result in response.json()["hits"]:
        images.append({
            "pageURL": result["pageURL"],
            "thumbnail": result["previewURL"],
            "tags": result["tags"],
        })
    page += 1

Таким образом, когда мы закончим, у нас будет 100 изображений или все изображения, если их меньше 100, сохраненные в массиве images. Затем мы можем продолжить делать с ними что-то полезное. Но прежде чем мы это сделаем, давайте поговорим о кэшировании.

Кэширование HTTP-запросов

Не рекомендуется делать один и тот же запрос к HTTP API более одного раза. Многие API имеют ограничения на использование, чтобы избежать чрезмерной нагрузки со стороны запрашивающих, а запрос требует времени и усилий как с их стороны, так и с нашей. Мы должны стараться не делать расточительных просьб, которые мы делали раньше. К счастью, есть удобный способ сделать это при использовании модуля Python requests: установить request-cache с расширением python -m pip install requests-cache. Это будет беспрепятственно записывать любые HTTP-вызовы, которые мы делаем, и сохранять результаты. Затем, позже, если мы снова выполним тот же вызов, мы вернем локально сохраненный результат, вообще не обращаясь за ним к API. Это экономит время и пропускную способность. Чтобы использовать requests_cache, импортируйте его и создайте CachedSession, а затем вместо requests.getиспользованияsession.getдля получения URL-адресов, и мы получим преимущество кэширования без дополнительных усилий:

import requests_cache
session = requests_cache.CachedSession('fruit_cache')
...
response = session.get(base_url, params=this_params)

Вывод

Чтобы увидеть результаты нашего запроса, нам нужно где-то отобразить изображения. Удобный способ сделать это — создать простую HTML-страницу, на которой показаны все изображения. Pixabay предоставляет маленькую миниатюру каждого изображения, которое вызывается previewURLв ответе API, поэтому мы можем составить HTML-страницу, которая показывает все эти миниатюры и связывает их с главной страницей Pixabay, с которой мы можем выбрать загрузку изображений, которые мы хотите и кредит фотографа. Таким образом, каждое изображение на странице может выглядеть так:

<li>
    <a href="https://pixabay.com/photos/berries-fruits-food-blackberries-2277/">
        <img src="https://cdn.pixabay.com/photo/2010/12/13/10/05/berries-2277_150.jpg" alt="berries, fruits, food">
    </a>
</li>

Мы можем построить это из нашего imagesсписка, используя понимание списка, а затем объединить все результаты в одну большую строку с помощью «\n».join():

html_image_list = [
    f"""<li>
            <a href="{image["pageURL"]}">
                <img src="{image['thumbnail']}" alt="{image["tags"]}">
            </a>
        </li>
    """
    for image in images
]
html_image_list = "\n".join(html_image_list)

В этот момент, если мы напишем очень простую HTML-страницу, содержащую этот список, ее легко открыть в веб-браузере для быстрого обзора всех результатов поиска, которые мы получили от API, и щелкнуть любой из них, чтобы перейти к полная страница Pixabay для загрузки:

html = f"""<!doctype html>
<html><head><meta charset="utf-8">
<title>Pixabay search for {base_params['q']}</title>
<style>
ul {{
    list-style: none;
    line-height: 0;
    column-count: 5;
    column-gap: 5px;
}}
li {{
    margin-bottom: 5px;
}}
</style>
</head>
<body>
<ul>
{html_image_list}
</ul>
</body></html>
"""
output_file = f"searchresults-{base_params['q']}.html"
with open(output_file, mode="w", encoding="utf-8") as fp:
    fp.write(html)
print(f"Search results summary written as {output_file}")

Оцените статью
bestprogrammer.ru
Добавить комментарий