Мэтиз. Изучаем Python. Crash course2 n d e d i t i o na h a n d s o n, p r o j e c t b a s e d i n t r o d u c t i o n t o p r o g r a m m i n g
Скачать 6.2 Mb.
|
ПРИМЕЧАНИЕ Если эта команда не работает в macOS, попробуйте снова выполнить команду без флага --user . Обработка ответа API Теперь мы напишем программу, которая выдает вызов API для поиска на Github проектов Python с наибольшим количеством звезд: python_repos.py ❶ import requests # Создание вызова API и сохранение ответа. ❷ url = 'https://api.github.com/search/repositories?q=language:python&sort=stars' ❸ headers = {'Accept': 'application/vnd.github.v3+json'} ❹ r = requests.get(url, headers=headers) ❺ print(f"Status code: {r.status_code}") # Сохранение ответа API в переменной. ❻ response_dict = r.json() # Обработка результатов. print(response_dict.keys()) В точке импортируется модуль requests . В точке URL-адрес вызова API со- храняется в переменной url . В настоящее время GitHub использует третью версию API, поэтому для вызова API определяются заголовки , которые явно требуют использовать эту версию API. После этого модуль requests используется для вы- зова . Использование API веб-приложений 377 Мы вызываем метод get() и передаем ему URL и заголовок, а объект ответа со- храняется в переменной r . Объект ответа содержит атрибут status_code , в котором хранится признак успешного выполнения запроса. (Код 200 — признак успешного ответа.) В точке программа выводит значение status_code , чтобы вы могли убе- диться в том, что вызов был обработан успешно. API возвращает информацию в формате JSON, поэтому в программе используется метод json() для преобразования информации в словарь Python. Полученный словарь сохраняется в переменной response_dict Наконец, программа выводит ключи словаря response_dict , и мы видим следую- щее: Status code: 200 dict_keys(['total_count', 'incomplete_results', 'items']) Код статуса 200 означает, что запрос был обработан успешно. Словарь ответа со- держит всего три ключа: 'total_count' , 'incomplete_results' и 'items' . Присмо- тримся повнимательнее к словарю ответа. ПРИМЕЧАНИЕ Подобные простые вызовы должны возвращать полный набор ре- зультатов, поэтому значение, связанное с 'incomplete_results', можно достаточно безопасно игнорировать . Но если ваша программа выдает более сложные вызовы API, обязательно проверяйте это значение . Работа со словарем ответа Итак, полученная при вызове API информация хранится в словаре, и мы можем заняться работой с данными. Для начала построим сводку с обобщенными сведе- ниями — это позволит убедиться в том, что вызов вернул ожидаемую информацию, и перейти к анализу интересующих данных. python_repos.py import requests # Создание вызова API и сохранение ответа. # Сохранение ответа API в переменной. response_dict = r.json() ❶ print(f"Total repositories: {response_dict['total_count']}") # Анализ информации о репозиториях. ❷ repo_dicts = response_dict['items'] print(f"Repositories returned: {len(repo_dicts)}") # Анализ первого репозитория. ❸ repo_dict = repo_dicts[0] ❹ pprint(f"\nKeys: {len(repo_dict)}") ❺ for key in sorted(repo_dict.keys()): print(key) 378 Глава 17 • Работа с API В точке выводится значение, связанное с 'total_count' , которое представляет общее количество репозиториев Python в GitHub. Значение, связанное с 'items' , представляет собой список со словарями, каждый из которых содержит данные об одном репозитории Python. В точке этот список словарей сохраняется в repo_dicts . Затем программа выводит длину repo_dicts , чтобы пользователь видел, по какому количеству репозиториев имеется инфор- мация. Чтобы получить первое представление об информации, возвращенной по каждому репозиторию, программа извлекает первый элемент из repo_dicts и сохраняет его в repo_dict . Затем программа выводит количество ключей в словаре — это зна- чение определяет объем доступной информации . В точке выводятся все ключи словаря; по ним можно понять, какая информация включена в ответ. Из сводки начинает вырисовываться более четкая картина полученных данных: Status code: 200 Total repositories: 3494030 Repositories returned: 30 ❶ Keys: 73 archive_url archived assignees_url url watchers watchers_count API GitHub возвращает подробную информацию о каждом репозитории: в repo_ dict 73 ключа . Просмотр ключей дает представление о том, какую информацию можно извлечь о проекте. (Чтобы узнать, какую информацию можно получить через API, следует либо прочитать документацию, либо проанализировать инфор- мацию в коде, как мы и поступаем.) Прочитаем значения некоторых ключей repo_dict : python_repos.py # Анализ информации о репозиториях. repo_dicts = response_dict['items'] print(f"Repositories returned: {len(repo_dicts)}") # Анализ первого репозитория. repo_dict = repo_dicts[0] print("\nSelected information about first repository:") ❶ print(f"Name: {repo_dict['name']}") ❷ print(f"Owner: {repo_dict['owner']['login']}") ❸ print(f"Stars: {repo_dict['stargazers_count']}") print(f"Repository: {repo_dict['html_url']}") Использование API веб-приложений 379 ❹ print(f"Created: {repo_dict['created_at']}") ❺ print(f"Updated: {repo_dict['updated_at']}") print(f"Description: {repo_dict['description']}") В программе выводятся значения, связанные с некоторыми ключами словаря пер- вого репозитория. В точке выводится имя проекта. Владельца проекта представ- ляет целый словарь, поэтому в точке ключ owner используется для обращения к словарю, представляющему владельца, после чего ключ login используется для получения регистрационного имени владельца. В точке выводится количество звезд, заработанных проектом, и URL репозитория GitHub проекта. Далее выво- дится дата создания и последнего обновления репозитория . В завершение выводится описание репозитория; вывод должен выглядеть примерно так: Status code: 200 Total repositories: 3494032 Repositories returned: 30 Selected information about first repository: Name: awesome-python Owner: vinta Stars: 61549 Repository: https://github.com/vinta/awesome-python Created: 2014-06-27T21:00:06Z Updated: 2019-02-17T04:30:00Z Description: A curated list of awesome Python frameworks, libraries, software and resources Из вывода видно, что на момент написания книги самым «звездным» проектом Python на GitHub был проект awesome-python, владельцем которого является пользователь vinta, и звезды этот проект получил более чем от 60 000 пользователей GitHub. Мы видим URL репозитория проекта, дату создания (июнь 2014 г.) и то, что проект недавно обновлялся. Наконец, из описания следует, что awesome-python содержит список самых популярных ресурсов Python. Сводка самых популярных репозиториев При построении визуализации этих данных на диаграмму необходимо нанести более одного репозитория. Напишем цикл для вывода информации о каждом ре- позитории, возвращаемом вызовом API, чтобы все эти репозитории можно было включить в визуализацию: python_repos.py # Анализ информации о репозиториях. repo_dicts = response_dict['items'] print(f"Repositories returned: {len(repo_dicts)}") ❶ print("\nSelected information about each repository:") ❷ for repo_dict in repo_dicts: 380 Глава 17 • Работа с API print(f"\nName: {repo_dict['name']}") print(f"Owner: {repo_dict['owner']['login']}") print(f"Stars: {repo_dict['stargazers_count']}") print(f"Repository: {repo_dict['html_url']}") print(f"Description: {repo_dict['description']}") В точке выводится приветственное сообщение. В точке перебираются все словари в repo_dicts . Внутри цикла выводится имя каждого проекта, его владелец, количество звезд, URL на GitHub и краткое описание проекта: Status code: 200 Total repositories: 3494040 Repositories returned: 30 Selected information about each repository: Name: awesome-python Owner: vinta Stars: 61549 Repository: https://github.com/vinta/awesome-python Description: A curated list of awesome Python frameworks, libraries, software and resources Name: system-design-primer Owner: donnemartin Stars: 57256 Repository: https://github.com/donnemartin/system-design-primer Description: Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards. Name: python-patterns Owner: faif Stars: 19058 Repository: https://github.com/faif/python-patterns Description: A collection of design patterns/idioms in Python В этих результатах встречаются интересные проекты; возможно, вам стоит при- смотреться к некоторым из них… Но не увлекайтесь, потому что мы собираемся создать визуализацию, которая существенно упростит чтение результатов. Проверка ограничений частоты обращений API Многие API ограничивают частоту обращений; иначе говоря, существует предел для количества запросов в определенный промежуток времени. Чтобы узнать, не приближаетесь ли вы к ограничениям GitHub, введите в браузере адрес https://api . github .com/rate_limit . Вы получите ответ, который выглядит примерно так: { "resources": { "core": { "limit": 60, "remaining": 58, Использование API веб-приложений 381 "reset": 1550385312 }, ❶ "search": { ❷ "limit": 10, ❸ "remaining": 8, ❹ "reset": 1550381772 } }, В этих данных нас интересует частота обращений для поискового API . В точке видно, что предельная частота составляет 10 запросов в минуту и что на текущую минуту осталось еще 8 запросов . Значение reset представляет Unix-время, или эпохальное время (число секунд, прошедших с полуночи 1 января 1970 г.) момента, когда произойдет сброс квоты . При достижении предельного количества обраще- ний вы получите короткий ответ, уведомляющий о достижении предела API. Если это произойдет, просто подождите, пока квота будет сброшена. ПРИМЕЧАНИЕ Многие API требуют регистрации и получения ключа API для соверше- ния вызовов . На момент написания для GitHub такого требования не было, но если вы получите ключ API, предельная частота обращений для ваших программ значительно увеличится . Визуализация репозиториев с использованием Plotly Теперь, с появлением интересных данных, мы построим визуализацию, демонстри- рующую относительную популярность проектов Python в GitHub. Мы построим интерактивную столбцовую диаграмму: высота каждого столбца будет представ- лять количество звезд у проекта. Щелчок на столбце будет открывать домашнюю страницу проекта на GitHub. Сохраните копию программы, над которой вы рабо- таете, под именем python_repos_visual .py , а затем приведите ее к следующему виду: python_repos_visual.py import requests ❶ from plotly.graph_objs import Bar from plotly import offline ❷ # Создание вызова API и сохранение ответа. url = 'https://api.github.com/search/repositories?q=language:python&sort=stars' headers = {'Accept': 'application/vnd.github.v3+json'} r = requests.get(url, headers=headers) print(f"Status code: {r.status_code}") # Обработка результатов. response_dict = r.json() repo_dicts = response_dict['items'] ❸ repo_names, stars = [], [] for repo_dict in repo_dicts: 382 Глава 17 • Работа с API repo_names.append(repo_dict['name']) stars.append(repo_dict['stargazers_count']) # Построение визуализации. ❹ data = [{ 'type': 'bar', 'x': repo_names, 'y': stars, }] ❺ my_layout = { 'title': 'Most-Starred Python Projects on GitHub', 'xaxis': {'title': 'Repository'}, 'yaxis': {'title': 'Stars'}, } fig = {'data': data, 'layout': my_layout} offline.plot(fig, filename='python_repos.html') Мы импортируем класс Bar и модуль offline из plotly . Импортировать класс Layout не нужно, потому что для определения макета будет использоваться сло- варь, как это делалось со списком data в проекте с землетрясениями из главы 16. Затем выводится статус ответа на вызов API, чтобы мы сразу узнали о возможной проблеме с вызовом API . Часть кода обработки ответа API удалена, потому что фаза исследования данных осталась позади; мы знаем, что получены именно те данные, которые нам нужны. В точке создаются два пустых списка для хранения данных, включаемых в диа- грамму. Нам понадобится имя каждого проекта (для пометки столбцов) и количе- ство звезд, определяющее высоту столбцов. В цикле имя каждого проекта и коли- чество звезд присоединяются к соответствующему списку. Затем определяется список data . Он содержит словарь вроде того, который использовался в главе 16: он определяет тип диаграммы и содержит значения по осям x и y . По оси x размещаются названия проектов, а по оси y — количество звезд, назначенное каждому проекту. В точке макет диаграммы определяется при помощи словаря. Вместо того чтобы создавать экземпляр класса Layout , мы строим словарь с нужными спецификаци- ями макета. Далее назначается заголовок для диаграммы в целом, а также метки каждой оси. Полученная диаграмма изображена на рис. 17.1. Мы видим, что несколько первых проектов существенно популярнее остальных, но все эти проекты занимают важное место в экосистеме Python. Доработка диаграмм Plotly Немного доработаем стилевое оформление диаграммы. Как было показано в главе 16, все директивы стилевого оформления включаются в виде пар «ключ- значение» в словари data и my_layout Использование API веб-приложений 383 Рис. 17.1. Проекты Python на GitHub с наибольшим количеством звезд Изменения в объекте data влияют на вид столбцов. Ниже приведена обновленная версия объекта data для диаграммы, которая назначает конкретный цвет и хорошо заметную границу для каждого столбца: python_repos_visuals.py data = [{ 'type': 'bar', 'x': repo_names, 'y': stars, 'marker': { 'color': 'rgb(60, 100, 150)', 'line': {'width': 1.5, 'color': 'rgb(25, 25, 25)'} }, 'opacity': 0.6, }] Настройки marker влияют на внешний вид столбцов. Мы назначаем столбцам синий цвет и указываем, что они должны иметь серую границу толщиной 1,5 пик- села. Также для столбцов устанавливается прозрачность 0.6 , чтобы изображение казалось немного размытым. Затем мы внесем изменения в my_layout : python_repos_visual.py my_layout = { 'title': 'Most-Starred Python Projects on GitHub', 384 Глава 17 • Работа с API ❶ 'titlefont': {'size': 28}, ❷ 'xaxis': { 'title': 'Repository', 'titlefont': {'size': 24}, 'tickfont': {'size': 14}, }, ❸ 'yaxis': { 'title': 'Stars', 'titlefont': {'size': 24}, 'tickfont': {'size': 14}, }, } Ключ 'titlefont' добавлен для определения размера шрифта общего заголовка диаграммы . В словарь 'xaxis' добавляются настройки для управления размером шрифта заголовка оси x ( 'titlefont' ) и меток делений ( 'tickfont' ) . Так как речь идет об отдельных вложенных словарях, вы можете включить ключи для цвета и семейства шрифтов заголовков осей и меток делений. В точке аналогичные настройки определяются для оси y На рис. 17.2 изображена диаграмма с измененным оформлением. Рис. 17.2. Диаграмма с улучшенным оформлением Добавление подсказок В Plotly при наведении указателя мыши на отдельный столбец отображается информация, которую этот столбец представляет. В текущей версии экранная подсказка (tooltip) отображает количество звезд проекта. Давайте создадим не- стандартную подсказку, которая также будет выводить описание каждого проекта. Использование API веб-приложений 385 Чтобы сгенерировать подсказки и изменить объект data , необходимо извлечь до- полнительные данные: python_repos_visual.py # Обработка результатов. response_dict = r.json() repo_dicts = response_dict['items'] ❶ repo_names, stars, labels = [], [], [] for repo_dict in repo_dicts: repo_names.append(repo_dict['name']) stars.append(repo_dict['stargazers_count']) ❷ owner = repo_dict['owner']['login'] description = repo_dict['description'] ❸ label = f"{owner} {description}" labels.append(label) # Построение визуализации. data = [{ 'type': 'bar', 'x': repo_names, 'y': stars, ❹ 'hovertext': labels, 'marker': { 'color': 'rgb(60, 100, 150)', 'line': {'width': 1.5, 'color': 'rgb(25, 25, 25)'} }, 'opacity': 0.6, }] Сначала определяется новый пустой список labels для хранения текста, который должен выводиться для каждого проекта . В цикле, где происходит обработка дан- ных, мы извлекаем владельца и описание для каждого проекта . Plotly позволяет использовать разметку HTML в текстовых элементах, поэтому мы сгенерируем для метки текст с разрывом строки ( /> ) между именем владельца проекта и описа- нием . Затем метка сохраняется в списке labels В словарь data добавляется запись с ключом 'hovertext' , которой присваивается только что созданный список . При создании каждого столбца Plotly извлекает метки из списка и выводит их только в тот момент, когда пользователь задерживает указатель мыши над столбцом. Полученная диаграмма изображена на рис. 17.3. Добавление активных ссылок на диаграмму Так как Plotly позволяет использовать HTML в текстовых элементах, диаграмму можно легко дополнить ссылками. Используем метки оси x для того, чтобы пользо- 386 Глава 17 • Работа с API Рис. 17.3. При наведении указателя мыши на столбец выводится информация о владельце и описание проекта ватель мог открыть домашнюю страницу проекта на GitHub. Необходимо извлечь URL-адреса из данных и использовать их при генерировании меток для оси x : python_repos_visual.py # Обработка результатов. response_dict = r.json() repo_dicts = response_dict['items'] ❶ repo_links, stars, labels = [], [], [] for repo_dict in repo_dicts: repo_name = repo_dict['name'] ❷ repo_url = repo_dict['html_url'] ❸ repo_link = f"{repo_name}" repo_links.append(repo_link) stars.append(repo_dict['stargazers_count']) # Построение визуализации. data = [{ 'type': 'bar', ❹ 'x': repo_links, 'y': stars, }] |