Web应用编程接口 (API)自动请求网站的特定信息而不是整个网页,再对这些信息进行可视化。由于这样编写的程序始终使用最新的数据来生成可视化,因此即便数据瞬息万变,它呈现的信息也都是最新的。
Web API是网站的一部分,用于与使用非常具体的URL请求特定信息的程序交互。这种请求称为API调用。请求的数据将以易于处理的格式(如JSON或CSV)返回。依赖于外部数据源的大多数应用程序都依赖于API调用,如集成社交媒体网站的应用序。
处理API响应
执行API调用并处理结果,找出GitHub上星级最高的Python项目:
python_repos.py
import requests
#执行API调用并存储响应
url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url) #使用requests 来执行调用,将响应对象存储在变量r中
print("Status code:",r.status_code)#响应对象包含一个名为status_code的属性,它让我们知道请求是否成功(状态码200表示请求成功)
#将API响应存储在一个变量中
response_dict = r.json()
#处理结果
print(response_dict.keys())
处理响应字典
将API调用返回的信息存储到字典中后,就可以处理这个字典中的数据了。下面生成一些概述这些信息的输出。可确认收到了期望的信息,进而可以开始研究感兴趣的信息:
import requests
#执行API调用并存储响应
url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:",r.status_code)
#将API响应存储在一个变量中
response_dict = r.json()
print("Total repositories:",response_dict['total_count'])#指出GitHub包含多少个Python仓库
#探索有关仓库的信息
repo_dicts=response_dict['items']#response_dict字典存储在列表中,列表里每个字典都包含有关一个Python仓库的信息
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)
GitHub的API返回有关每个仓库的大量信息:repo_dict 包含68个键(见❶)。通过仔细查看这些键,可大致知道可提取有关项目的哪些信息(要准确地获悉API将返回哪些信息,要么阅读文档,要么像此处这样使用代码来查看这些信息)。
Status code: 200
Total repositories: 713062
Repositories returned: 30
❶ Keys: 68
archive_url
assignees_url
blobs_url
--snip--
url
watchers
watchers_count
概述最受欢迎的仓库
对这些数据进行可视化时,我们需要涵盖多个仓库。下面就来编写一个循环,打印API调用返回的每个仓库的特定信息,以便能够在可视化中包含所有这些信息:
--snip--
#研究第一个仓库
repo_dict = repo_dicts[0]
print("\nKeys:",len(repo_dict))
for key in sorted(repo_dict.keys()):
print(key)
print("\nSelected information about first repository:")
for repo_dict in repo_dicts:
print('\nName:', 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'])
监视API的速率限制
大多数API都存在速率限制,即你在特定时间内可执行的请求数存在限制。要获悉你是否接近了GitHub的限制,请在浏览器中输入https://api.github.com/rate_limit ,你将看到类似于下面的响应:
{
"resources": {
"core": {
"limit": 60,
"remaining": 60,
"reset": 1521446243
},
"search": {#搜索API的速率限制
"limit": 10,#极限为每分钟10个请求
"remaining": 10,#在当前这一分钟内,我们还可执行10个请求
"reset": 1521442703#配额将重置的Unix时间或新纪元时间(1970年1月1日午夜后多少秒)
},
"graphql": {
"limit": 0,
"remaining": 0,
"reset": 1521446243
}
},
"rate": {
"limit": 60,
"remaining": 60,
"reset": 1521446243
}
}
使用Pygal可视化仓库
有了一些有趣的数据后,我们来进行可视化,呈现GitHub上Python项目的受欢迎程度。我们将创建一个交互式条形图:条形的高度表示项目获得了多少颗星。单击条形将带你进入项目在GitHub上的主页。下面是首次尝试这样做:
import requests
import pygal
from pygal.style import LightColorizedStyle as LCS,LightenStyle as LS
#执行API调用并存储响应
url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:",r.status_code)
#将API响应存储在一个变量中
response_dict = r.json()
print("Total repositories:",response_dict['total_count'])#指出GitHub包含多少个Python仓库
#探索有关仓库的信息
repo_dicts=response_dict['items']#response_dict字典存储在列表中,列表里每个字典都包含有关一个Python仓库的信息
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)#创建条形图,让标签绕x轴旋转45度(x_label_rotation=45 ),隐藏图例(show_legend=False )
chart.title = 'Most-Starred Python Projects on GitHub'#指定标题
chart.x_labels=names#横座标标签
chart.add('',stars)#添加数据,标签设置成空字符串
chart.render_to_file('python_repos.svg')
改进Pygal图表
进行多个方面的定制,因此先来稍微调整代码的结构,创建一个配置对象,在其中包含要传递给Bar() 的所有定制:
--snip--
#可视化
my_style = LS('#333366',base_style=LCS)
my_config = pygal.Config()#创建Pygal类Config实例,通过修改my_config定制图表外观
my_config.x_label_rotation = 45#让标签绕x轴旋转45度(x_label_rotation=45 )
my_config.show_legend = False#隐藏图例(show_legend=False )
my_config.title_font_size = 24#图表标题
my_config.lable_font_size =14#副标签(X轴项目名及Y轴大部分数字)
my_config.major_label_font_size = 18#主标签(Y轴5000整数倍的刻度)
my_config.truncate_label =15#将较长的项目名缩短为15个字符
my_config.show_y_guides = False#隐藏图表中的水平线
my_config.width = 1000#自定义宽度
chart = pygal.Bar(my_config,style=my_style)#通过my_config传递所有配置设置
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels=names
chart.add('',stars)
chart.render_to_file('python_repos.svg')
添加自定义工具提示
在Pygal中,将鼠标指向条形将显示它表示的信息,这通常称为工具提示 。在这个示例中,当前显示的是项目获得了多少个星。下面来创建一个自定义工具提示,以同时显示项目的描述。来看一个简单的示例,它可视化前三个项目,并给每个项目对应的条形都指定自定义标签。为此,我们向add() 传递一个字典列表,而不是值列表:
bar_descriptions.py
import pygal
from pygal.style import LightColorizedStyle as LCS,LightenStyle as LS
my_style = LS('#333366',base_style = LCS)
chart = pygal.Bar(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' 相关联的字符串给条形创建工具提示。第一个字典将创建一个条形,用于表示一个获得了16 101颗星、工具提示为Description of httpie的项目。方法add() 接受一个字符串和一个列表。这里调用add() 时,我们传入了一个由表示条形的字典组成的列表(plot_dicts )。结果显示了一个工具提示:除默认工具提示(获得的星数)外,Pygal还显示了我们传入的自定义提示。
--snip--
#探索有关仓库的信息
repo_dicts=response_dict['items']#response_dict字典存储在列表中,列表里每个字典都包含有关一个Python仓库的信息
names,plot_dicts = [],[]
for repo_dict in repo_dicts:
names.append(repo_dict['name'])
plot_dict ={
'value':repo_dict['stargazers_count'],
'label':str(repo_dict['description']),
}
plot_dicts.append(plot_dict)
#可视化
my_style = LS('#333366',base_style=LCS)
--snip--
chart.add('',plot_dicts)
chart.render_to_file('python_repos.svg')
在图表中添加可单击的链接
--snip--
plot_dict ={
'value':repo_dict['stargazers_count'],
'label':str(repo_dict['description']),
'xlink':repo_dict['html_url'],
}
--snip--
Pygal根据与键'xlink' 相关联的URL将每个条形都转换为活跃的链接。单击图表中的任何条形时,都将在浏览器中打开一个新的标签页,并在其中显示相应项目的GitHub页面。至此,你对API获取的数据进行了可视化,它是交互性的,包含丰富的信息!
import requests
from operator import itemgetter
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS
#执行API调用并存储响应
url = 'https://hacker-news.firebaseio.com/v0/topstories.json'
r = requests.get(url)
#打印请求状态(200表示成功)
print("Status code:",r.status_code)
#处理有关每篇文章的信息
#将包含ID信息的响应文本转换为列表
submission_ids = r.json()
#创建空列表存储文章信息(字典)
submission_dicts = []
#通过ID遍历前30篇文章,并执行API调用
for submission_id in submission_ids[:3]:
#对于每篇文章都执行一个API调用
url = ('https://hacker-news.firebaseio.com/v0/item/' +
str(submission_id) + '.json')
submission_r = requests.get(url)
print(submission_r.status_code)
response_dict = submission_r.json()
submission_dict = {
'title': response_dict['title'],#标题
'link': 'http://news.ycombinator.com/item?id=' +
str(submission_id),#讨论页面链接
#不确定某个键是否包含在字典中时,使用方法dict.get()
#它在指定的键存在时返回与之相关联的值
#并在指定的键不存在时返回你指定的值(这里是0)
'comments': response_dict.get('descendants', 0)#评论数
}
submission_dicts.append(submission_dict)
#根据comments降序排列
submission_dicts = sorted(submission_dicts, key = itemgetter('comments'),
reverse = True)
for submission_dict in submission_dicts:
print("\nTitle:",submission_dict['title'])
print("Discussion link:",submission_dict['link'])
print("Comments:",submission_dict['comments'])
titles,plot_dicts = [],[]
for submission_dict in submission_dicts:
titles.append(submission_dict['title'])
plot_dicts = {
'value':submission_dict['comments'],
'label':submission_dict['title'],
'xlink':submission_dict['link'],
}
plot_dicts.append(plot_dict)
my_style = LS('#333366',base_style = LCS)
my_style.title_font_size = 24
my_style.label_font_size = 14
my_style.major_lable_font_size = 18
my_config = pygal.Config()
my_config.x_label_rotation = 45
my_config.show_lenged = False
my_config.truncate_label = 15 #将较长的项目名缩短为15个字符
my_config.show_y_guides = False #隐藏图表中的水平线
my_config.width = 1000
my_config.y_title = 'Number of Comments'
chart = pygal.Bar(my_config, style = my_style)
chart.title = 'Most Active Discussions on Hacker News'
chart.x_labels = titles
chart.add('',plot_dicts)
chart.render_to_file('hn_discussions.svg')