Python编程学习笔记 - 使用Web API获取数据进行可视化

1. 使用Web API

Web API 是网站的一部分,用于与使用非常具体的URL请求特定信息的程序交互。这种请求称为API调用。请求的数据将以易于处理的格式(如JSON或CSV)返回。依赖于外部数据源的大多数应用程序都依赖于API调用,如集成社交媒体网站的应用程序。

1.1 Git和GitHub

基于来自GitHub的信息,我们将使用GibHub的API来请求有关网站中Python项目的信息,然后使用Pygal生成交互式可视化,以呈现这些项目的受欢迎程度。

GitHub(https://github/.com) 的名字源自Git,Git是一个分布式版本控制系统。GitHub上的项目都存储在仓库中,后者包含与项目相关联的一切:代码、项目参与者的信息、问题或bug报告等。

对于喜欢的项目,GitHub用户给它加星(star)来表示支持,用户还可以跟踪他可能想使用的项目。我们将编写一个程序,它自动下载GitHub上星级最高的Python项目的信息,并对这些信息进行可视化。

1.2 使用API调用请求数据

GitHub的API让我们能够通过API调用来请求各种信息。要知道API调用是什么样的,请在浏览器的地址栏输入如下地址并按回车键:
https://api.github.com/search/repositories?q=language:python&sort=stars

这个调用返回GitHub当前托管了多少个Python项目,还有有关最受欢迎的Python仓库的信息。下面来仔细研究这个调用。第一部分(https://api.github.com/) 将请求发送到GitHub网站中响应API调用的部分;接下来的一部分(search/repositories)让API搜索GitHub上的所有仓库。repositories后面的问号指出我们要传递一个实参。q表示查询,而等号让我们能够开始制定查询(q=)。通过使用language:python,我们指出只想获取主要语言为Python的仓库信息。最后一部分(&sort=stars)制定将项目按其获得的星级进行排序。

下面显示了响应的前几行。从响应可知,该URL并不适合人工输入:

{
“total_count”: 3223799,
“incomplete_results”: false,
“items”: [
{
“id”: 21289110,
“node_id”: “MDEwOlJlcG9zaXRvcnkyMTI4OTExMA==”,
“name”: “awesome-python”,
“full_name”: “vinta/awesome-python”,
“private”: false,
“owner”: {
“login”: “vinta”,
“id”: 652070,

从第二行输出可知,目前GitHub总共有3223799个Python项目。“incomplete_results"的值为false,据此我们知道请求是成功的(它并非不完整)。倘若GitHub无法全面处理该API,它返回的这个值将为true。接下来的列表中显示了返回的"items”,其中包含GitHub上最受欢迎的Python项目的详细信息。

1.3 安装requests包

requests包让Python程序能够轻松地向网站请求信息以及检查返回的响应。要安装requests,请执行类似于下面的命令:

pip install requests

1.4 处理API响应

下面编写一个程序,它执行API调用并处理结果,找出GitHub上星级最高的Python项目:

python_repos.py 代码

import requests

url='https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:", r.status_code)

response_dict = r.json()

print(response_dict.keys())

我们使用方法json()将这些信息转换为一个Python字典。我们将转换得到的字典存储在response_dict中。

最后,我们打印response_dict中的键。输出如下:

Status code: 200
dict_keys([‘total_count’, ‘incomplete_results’, ‘items’])

状态码为200,因此我们知道请求成功了。响应字典只包含三个键:‘total_count’,‘incomplete_results’,‘items’。

1.5 处理响应字典

将API调用返回的信息存储到字典中后,就可以处理这个字典中的数据了。下面来生成一些概述这些信息的输出。这是一种不错的方式,可确认收到了期望的信息,进而可以开始研究感兴趣的信息:

import requests

url='https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:", r.status_code)

response_dict = r.json()

print("Total repositories:", response_dict['total_count'])

repo_dicts = response_dict['items']
print("Repositories returned:", len(repo_dicts))

repo_dict = repo_dicts[0]
print("\nKeys:", len(repo_dict))
for key in sorted(repo_dict.keys()):
    print(key)

输出让我们对实际包含的数据有了更清晰的认识:

Status code: 200
Total repositories: 3223862
Repositories returned: 30
Keys: 73
archive_url
archived
assignees_url
blobs_url

watchers_count

GitHub的API返回有关每个仓库的大量信息: repo_dict包含73个键。通过仔细看这些键,可大致知道可提取有关项目的哪些信息(要准确地获悉API将返回哪些信息,要么阅读文档,要么向此处这样使用代码来查看这些信息)。

下面来提取repo_dict中的与一些键相关联的值:

import requests

url='https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:", r.status_code)

response_dict = r.json()

print("Total repositories:", response_dict['total_count'])

repo_dicts = response_dict['items']
print("Repositories returned:", len(repo_dicts))

repo_dict = repo_dicts[0]

print("\nSelected information about first repository:")
print('Name:', repo_dict['name'])
print('Owner:',repo_dict['owner']['login'])
print('Stars:',repo_dict['stargazers_count'])
print('Repository:',repo_dict['html_url'])
print('Created:',repo_dict['created_at'])
print('Updated:',repo_dict['updated_at'])    
print('Description:',repo_dict['description'])

在这里,我们打印了表示第一个仓库的字典中与很多键相关联的值。我们打印了项目的名称(Name),所有者(Owner),登录名(Login),我们还打印项目获得了多少个星的评级,以及项目在GitHub仓库的URL。接下来,我们显示项目的创建时间(Created)和最后一次更新的时间(Updated)。最后,我们打印仓库的描述。输出类似于下面这样:

Status code: 200
Total repositories: 3229766
Repositories returned: 30

Selected information about first repository:
Name: awesome-python
Owner: vinta
Stars: 57760
Repository: https://github.com/vinta/awesome-python
Created: 2014-06-27T21:00:06Z
Updated: 2018-11-23T01:56:40Z
Description: A curated list of awesome Python frameworks, libraries, software and resources

从上述输出可知,当前,GitHub上星级最高的Python项目为awesome-python,其所有者为用户vinta,有57760个GitHub用户给这个项目加星。我们可以看到这个项目的仓库的URL,其创建时间为2014-06-27,且最近更新了。最后,给出了awesome-python的描述。

1.6 概述最受欢迎的仓库

对这些数据进行可视化时,我们需要涵盖多个仓库。下面就来打印编写一个循环,打印API调用返回时的每个仓库的特定信息,以便能够在可视化中包含所有这些信息:

import requests

url='https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:", r.status_code)

response_dict = r.json()

print("Total repositories:", response_dict['total_count'])

repo_dicts = response_dict['items']
print("Repositories returned:", len(repo_dicts))

print("\nSelected information about first repository:")
for repo_dict in repo_dicts:
    print('Name:', repo_dict['name'])
    print('Owner:',repo_dict['owner']['login'])
    print('Stars:',repo_dict['stargazers_count'])
    print('Repository:',repo_dict['html_url'])
    print('Description:',repo_dict['description'])

我们打印了一条说明性消息。接下来,我们遍历repo_dicts中的所有字典。这个循环中,我们打印每个项目的名称、所有者、星级、在GitHub上的URL以及描述:

Status code: 200
Total repositories: 3229791
Repositories returned: 30

Selected information about first repository:
Name: awesome-python
Owner: vinta
Stars: 57761
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: 52245
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: 18011
Repository: https://github.com/faif/python-patterns
Description: A collection of design patterns/idioms in Python

上述输出中有一些有趣的项目,可能值得再看一眼。大不要在这上面花费太多时间,因为我们即将创建的可视化可更容易地看清结果。

2. 使用Pygal可视化仓库

有了一些有趣的数据后,我们来进行可视化,呈现GitHub上Python项目的受欢迎程度。我们将创建一个交互式条形图:条形的高度表示项目获得了多少颗星。单击条形将带你进入项目在GitHub上的主页。下面是首次尝试这样做:

import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS

url='https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)

response_dict = r.json()

repo_dicts = response_dict['items']

names, stars = [], []

for repo_dict in repo_dicts:
    names.append(repo_dict['name'])
    stars.append(repo_dict['stargazers_count'])

my_style = LS('#333366', base_style=LCS)
chart = pygal.Bar(style=my_style, x_label_rotation=45, show_legend=False)
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names

chart.add('', stars)
    
chart.render_in_browser()    
#chart.render_to_file('Python_repos1.svg')

我们首先导入了pygal以及要应用于图表的Pygal样式。我们创建了两个空列表,用于存储将包含在图表中的信息。我们需要每个项目的名称,用于给条形加上标签,我们还需要知道项目获得了多少个星,用于确定条形的高度。在循环中,我们将项目的名称和获得的星数附加到这些列表的末尾。

接下来,我们使用LightenStyle类(别名LS)定义了一种样式,并将其基色设置成深蓝色。我们还传递了实参base_style,以使用LightColorizedStyle 类(别名LCS)。然后,我们使用Bar()创建一个简单的条形图,并向它传递my_style。我们还传递了另外两个样式实参:让标签绕x轴旋转45度(x_label_rotation=45),并隐藏了图例(show_legend=False),因为我们只在图表中绘制一个数据系列。接下来,我们给图表制定了标题,并将属性x_labels设置成列表names。

由于,我们不需要给这个数据系列添加标签,因此,在chart.add(’’, stars)处添加数据时,将标签设置成了空字符串。生成的图表如下所示:
Python编程学习笔记 - 使用Web API获取数据进行可视化_第1张图片

2.1 改进Pygal图表

下面来改进这个图表的样式。我们将进行多个方面的定制,因此先来稍微调整代码的结构,创建一个配置对象,在其中包含要传递给Bar()的所有定制:

import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS

url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)

response_dict = r.json()

repo_dicts = response_dict['items']

names, stars = [], []
    
for repo_dict in repo_dicts:
    names.append(repo_dict['name'])
    stars.append(repo_dict['stargazers_count'])

my_style = LS('#333366', base_style=LCS)

my_config = pygal.Config()
my_config.x_label_rotation = 45
my_config.show_legend      = False
my_config.title_font_size  = 24
my_config.label_font_size  = 14
my_config.major_label_font_size = 18
my_config.truncate_label   = 15
my_config.show_y_guides    = False
my_config.width            = 1000

chart = pygal.Bar(my_config, style=my_style)
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names

chart.add('', stars)

chart.render_to_file('Python_repos2.svg')

我们创建了一个Pygal类Config的实例,并将其命名为my_config。通过修改my_config的属性,可定制图表的外观。我们设置了两个属性x_label_rotation和show_legend,还设置了图表标题、副标签和主标签的字体大小。在这个图表中,副标签是x轴上的项目名以及y轴上的大部分数字。主标签是y轴上为5000整数倍的刻度;这些标签应更大,以与副标签区分开来。我们还使用truncate_label 将较长的项目缩短为15个字符(如果你将鼠标指向屏幕上被截短的项目名,将显示完整的项目名)。接下来,我们将show_y_guides设置为False,以隐藏图表中的水平线。最后,我们设置了自定义宽度,让图表更充分地利用浏览器中的可用空间。

在创建Bar实例时,我们将my_config作为第一个实参,从而通过一个实参传递所有的配置设置。我们可以通过my_config做任意数量的样式和配置修改。下图显示了重新设置式样后的图表:
Python编程学习笔记 - 使用Web API获取数据进行可视化_第2张图片

2.2 添加自定义工具提示

在Pygal中,将鼠标指向条形将显示它表示的信息,这通常称为工具提示。在这个示例中,当前显示的是项目获得了多少个星。下面来创建一个自定义工具提示,以同时显示项目的描述。

来看一个简单的示例,它可视化前三个项目,并给每个项目对应的条形都指向自定义标签。为此,我们向add()传递一个字典列表,而不是值列表:

import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS

my_style = LS('#333366', base_style=LCS)
chart = pygal.Bar(my_style=my_style, x_label_rotation=45, show_legend=False)

chart.title = 'Python Projects'
chart.x_labels = ['httpie','django','flask']

plot_dicts = [ 
	{'value': 16101, 'label': 'Description of httpie.'},
	{'value': 15028, 'label': 'Description of django.'},
	{'value': 14798, 'label': 'Description of flask.'},
	]

chart.add('', plot_dicts)
chart.render_to_file('bar_descriptions.svg')

我们定义了一个名为plot_dicts的列表,其中包含三个字典,分别针对项目对HTTPie, Django和Flask。每个字典都包含两个键: ‘value’和’label’。Pygal根据与键’value’相关联的数字来确定条形的高度,并使用与’label’相关联的字符串给条形创建工具提示。例如:第一个字典将创建一个条形,用于表示一个获得了16101颗星、工具提示为Description of httpie的项目。

方法add()接受一个字符串和一个列表。这里调用add()时,我们传入了一个由表示条形的字典组成的列表(plot_dicts)。下图显示了一个工具提示:除默认工具提示(获得的星数)外,Pygal还显示了我们传入的自定义提示:

Python编程学习笔记 - 使用Web API获取数据进行可视化_第3张图片

2.3 根据数据绘图

为根据数据绘图,我们将自动生成plot_dicts,其中包含API调用返回的30个项目的信息。完成这种工作的代码如下:

import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS

url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)

response_dict = r.json()

repo_dicts = response_dict['items']

names, plot_dicts = [], []
    
for repo_dict in repo_dicts:
    names.append(repo_dict['name'])
    s = str(repo_dict['description'])
    if len(s) > 60: 
        desc = s[:60]
    else:
        desc = s
    
    plot_dict = {
        'value': repo_dict['stargazers_count'],
        'label': desc,
        }
    plot_dicts.append(plot_dict)

my_style = LS('#333366', base_style=LCS)

my_config = pygal.Config()
my_config.x_label_rotation = 45
my_config.show_legend      = False
my_config.title_font_size  = 24
my_config.label_font_size  = 14
my_config.major_label_font_size = 18
my_config.truncate_label   = 15
my_config.show_y_guides    = False
my_config.width            = 1000

chart = pygal.Bar(my_config, style=my_style)
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names

chart.add(' ', plot_dicts)

#chart.render_in_browser()
chart.render_to_file('Python_repos3.svg')

我们创建了两个空列表names和plot_dicts。为生成x轴上的标签,我们依然需要列表names。

在循环内部,对于每个项目,我们都创建了字典plot_dict。在这个字典中,我们使用键’value’存储了星数,并使用键’label’存储了项目描述。接下来,我们将字典plot_dict附加到plot_dicts末尾。最后,我们将列表plot_dicts传递给add(),并绘制图形。生成的图形如下:
Python编程学习笔记 - 使用Web API获取数据进行可视化_第4张图片

2.4 在图表中添加可单击的链接

Pygal还允许你将图标中的每个条形用作网站的链接。为此,只需要添加移行代码,在为每个项目创建的字典中,添加一个键为’xlink’的键-值对:

for repo_dict in repo_dicts:
    s = str(repo_dict['description'])
    if len(s) > 60: 
        desc = s[:60]
    else:
        desc = s

    plot_dict = {
		'value': repo_dict['stargazers_count'],
		'label': desc,
		'xlink': repo_dict['html_url'],
		}
    plot_dicts.append(plot_dict)

Pygal根据与键’xlink’相关联的URL将每个条形都转换为活跃的链接。单击图表中的任何条形时,都将在浏览器中打开一个新的标签页,并在其中显示相应项目的GitHub页面。至此,我们对API获取的数据进行了可视化,它是交互性的,包含丰富的信息。

Python_repos.py 完整的代码

import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS

url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)

response_dict = r.json()

repo_dicts = response_dict['items']

names, plot_dicts = [], []
    
for repo_dict in repo_dicts:
    names.append(repo_dict['name'])
    s = str(repo_dict['description'])
    if len(s) > 60: 
        desc = s[:60]  #just display max. 60 chars of description
    else:
        desc = s

    plot_dict = {
		'value': repo_dict['stargazers_count'],
		'label': desc,
		'xlink': repo_dict['html_url'],
		}
    plot_dicts.append(plot_dict)

my_style = LS('#333366', base_style=LCS)

my_config = pygal.Config()
my_config.x_label_rotation      = 45
my_config.show_legend           = False
my_config.title_font_size       = 24
my_config.label_font_size       = 14
my_config.major_label_font_size = 18
my_config.truncate_label        = 15
my_config.show_y_guides         = False
my_config.width                 = 1000

chart = pygal.Bar(my_config, style=my_style)
chart.title    = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names
    
chart.add(' ', plot_dicts)

#chart.render_in_browser()
chart.render_to_file('Python_repos.svg')

如果你花点时间了解Web API, 稍微修改一下url,就可以得到GitHub网站上更多的最新数据的可视化结果。例如:
url = ‘https://api.github.com/search/repositories?q=language:cpp&sort=stars’ 所有C++项目,按其获得的星级进行排序
url = ‘https://api.github.com/search/repositories?q=ai&sort=stars’ 所有AI的项目,按其获得的星级进行排序

文章内容来自《Python编程 从入门到实践》 [美] Eric Matthes 袁国忠 译

你可能感兴趣的:(Python,跟我一起学Python)