import json import pygal 1 from pygal.style import RotateStyle --snip-- # 根据人口数量将所有的国家分成三组 cc_pops_1, cc_pops_2, cc_pops_3 = {}, {}, {} for cc, pop in cc_populations.items(): if pop < 10000000: --snip-- 2 wm_style = RotateStyle('#336699') 3 wm = pygal.Worldmap(style=wm_style) wm.title = 'World Population in 2010, by Country' --snip--
Pygal样式存储在模块style中,我们从这个模块中导入了样式RotateStyle(见1)。创建这 个类的实例时,需要提供一个实参——十六进制的RGB颜色(见2);Pygal将根据指定的颜色为 每组选择颜色。十六进制格式的RGB颜色是一个以井号(#)打头的字符串,后面跟着6个字符, 其中前两个字符表示红色分量,接下来的两个表示绿色分量,最后两个表示蓝色分量。每个分量 的取值范围为00(没有相应的颜色)~FF(包含最多的相应颜色)。如果你在线搜索hex color chooser (十六进制颜色选择器),可找到让你能够尝试选择不同的颜色并显示其RGB值的工具。这里使用 的颜色值(#336699)混合了少量的红色(33)、多一些的绿色(66)和更多一些的蓝色(99), 它为RotateStyle提供了一种淡蓝色基色。 RotateStyle返回一个样式对象,我们将其存储在wm_style中。为使用这个样式对象,我们在 创建Worldmap实例时以关键字实参的方式传递它(见3)。更新后的地图如图16-11所示。
前面的样式设置让地图的颜色更一致,也更容易区分不同的编组
16.2.10 加亮颜色主题
Pygal通常默认使用较暗的颜色主题。为方便印刷,我使用LightColorizedStyle加亮了地图的颜色。这个类修改整个图表的主题,包括背景色、标签以及各个国家的颜色。要使用这个样式, 先导入它:
wm_style = LightColorizedStyle
然后就可独立地使用LightColorizedStyle了,例如:
wm_style = LightColorizedStyle
然而使用这个类时,你不能直接控制使用的颜色,Pygal将选择默认的基色。要设置颜色, 可使用RotateStyle,并将LightColorizedStyle作为基本样式。为此,导入LightColorizedStyle 和RotateStyle:
from pygal.style import LightColorizedStyle, RotateStyle
再使用RotateStyle创建一种样式,并传入另一个实参base_style:
wm_style = RotateStyle('#336699', base_style=LightColorizedStyle)
这设置了较亮的主题,同时根据通过实参传递的颜色给各个国家着色。使用这种样式时,生 成的图表与本书的屏幕截图更一致。 尝试为不同的可视化选择合适的样式设置指令时,在import语句中指定别名会有所帮助:
from pygal.style import LightColorizedStyle as LCS, RotateStyle as RS
这样,样式定义将更短:
wm_style = RS('#336699', base_style=LCS)
通过使用几个样式设置指令,就能很好地控制图表和地图的外观。
16.3 小结
在本章中,你学习了:如何使用网上的数据集;如何处理CSV和JSON文件,以及如何提取 你感兴趣的数据;如何使用matplotlib来处理以往的天气数据,包括如何使用模块datetime,以及 如何在同一个图表中绘制多个数据系列;如何使用Pygal绘制呈现各国数据的世界地图,以及如 何设置Pygal地图和图表的样式。 有了使用CSV和JSON文件的经验后,你将能够处理几乎任何要分析的数据。大多数在线数 据集都可以以这两种格式中的一种或两种下载。学习使用这两种格式为学习使用其他格式的数据 做好了准备。 在下一章,你将编写自动从网上采集数据并对其进行可视化的程序。如果你只是将编程作为 业余爱好,学会这些技能可以增加乐趣;如果你有志于成为专业程序员,就必须掌握这些技能。
第17 章
使用API
17.1 使用 Web API
Web API是网站的一部分,用于与使用非常具体的URL请求特定信息的程序交互。这种请求 称为API调用。请求的数据将以易于处理的格式(如JSON或CSV)返回。依赖于外部数据源的大 多数应用程序都依赖于API调用,如集成社交媒体网站的应用程序。
17.1.1 Git 和 GitHub
本章的可视化将基于来自GitHub的信息,这是一个让程序员能够协作开发项目的网站。我们 将使用GitHub的API来请求有关该网站中Python项目的信息,然后使用Pygal生成交互式可视化, 以呈现这些项目的受欢迎程度。
GitHub(https://github.com/)的名字源自Git,Git是一个分布式版本控制系统,让程序员团队能 够协作开发项目。Git帮助大家管理为项目所做的工作,避免一个人所做的修改影响其他人所做的 修改。你在项目中实现新功能时,Git将跟踪你对每个文件所做的修改。确定代码可行后,你提交 所做的修改,而Git将记录项目最新的状态。如果你犯了错,想撤销所做的修改,可轻松地返回以 前的任何可行状态(要更深入地了解如何使用Git进行版本控制,请参阅附录D)。GitHub上的项目 都存储在仓库中,后者包含与项目相关联的一切:代码、项目参与者的信息、问题或bug报告等。 对于喜欢的项目,GitHub用户可给它加星(star)以表示支持,用户还可跟踪他可能想使用的项目。在本章中,我们将编写一个程序,它自动下载GitHub上星级最高的Python项目的信息, 并对这些信息进行可视化。
17.1.2 使用 API 调用请求数据
GitHub的API让你能够通过API调用来请求各种信息。要知道API调用是什么样的,请在浏览 器的地址栏中输入如下地址并按回车键:
这个调用返回GitHub当前托管了多少个Python项目,还有有关最受欢迎的Python仓库的信息。 下面来仔细研究这个调用。第一部分(https://api.github.com/)将请求发送到GitHub网站中响 应API调用的部分;接下来的一部分(search/repositories)让API搜索GitHub上的所有仓库。
repositories后面的问号指出我们要传递一个实参。q表示查询,而等号让我们能够开始指定 查询(q=)。通过使用language:python,我们指出只想获取主要语言为Python的仓库的信息。最 后一部分(&sort=stars)指定将项目按其获得的星级进行排序。 下面显示了响应的前几行。从响应可知,该URL并不适合人工输入。
{ "total_count": 713062, "incomplete_results": false, "items": [ { "id": 3544424, "name": "httpie", "full_name": "jkbrzt/httpie", --snip--
从第二行输出可知,编写本书时,GitHub总共有713 062个Python项目。"incomplete_results" 的值为false,据此我们知道请求是成功的(它并非不完整的)。倘若GitHub无法全面处理该API, 它返回的这个值将为true。接下来的列表中显示了返回的"items",其中包含GitHub上最受欢迎 的Python项目的详细信息。
17.1.3 安装 requests
requests包让Python程序能够轻松地向网站请求信,息以及检查返回的响应。要安装requests, 请执行类似于下面的命令:
$ pip install --user requests
如果你还没有使用过pip,请参阅12.2.1节(根据系统的设置,你可能需要使用这个命令的稍 微不同的版本)。
17.1.4 处理 API 响应
下面来编写一个程序,它执行API调用并处理结果,找出GitHub上星级最高的Python项目:
python_repos.py
1 import requests # 执行API调用并存储响应 2 url = 'https://api.github.com/search/repositories?q=language:python&sort=stars' 3 r = requests.get(url) 4 print("Status code:", r.status_code) # 将API响应存储在一个变量中 5 response_dict = r.json() # 处理结果 print(response_dict.keys())
在1处,我们导入了模块requests。在2处,我们存储API调用的URL,然后使用requests 来执行调用(见3)。我们调用get()并将URL传递给它,再将响应对象存储在变量r中。响应对 象包含一个名为status_code的属性,它让我们知道请求是否成功了(状态码200表示请求成功)。 在4处,我们打印status_code,核实调用是否成功了。 这个API返回JSON格式的信息,因此我们使用方法json()将这些信息转换为一个Python字典 (见5)。我们将转换得到的字典存储在response_dict中。 最后,我们打印response_dict中的键。输出如下:
Status code: 200 dict_keys(['items', 'total_count', 'incomplete_results'])
状态码为200,因此我们知道请求成功了。响应字典只包含三个键:'items'、'total_count' 和'incomplete_results'。
注意
像这样简单的调用应该会返回完整的结果集,因此完全可以忽略与'incomplete_results' 相关联的值。但执行更复杂的API调用时,程序应检查这个值。
17.1.5 处理响应字典
将API调用返回的信息存储到字典中后,就可以处理这个字典中的数据了。下面来生成一些 概述这些信息的输出。这是一种不错的方式,可确认收到了期望的信息,进而可以开始研究感兴 趣的信息:
python_repos.py
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() 1 print("Total repositories:", response_dict['total_count']) # 探索有关仓库的信息 2 repo_dicts = response_dict['items'] print("Repositories returned:", len(repo_dicts)) # 研究第一个仓库 3 repo_dict = repo_dicts[0] 4 print("\nKeys:", len(repo_dict)) 5 for key in sorted(repo_dict.keys()): print(key)
在1处,我们打印了与'total_count'相关联的值,它指出了GitHub总共包含多少个Python仓 库。
与'items'相关联的值是一个列表,其中包含很多字典,而每个字典都包含有关一个Python 仓库的信息。在2处,我们将这个字典列表存储在repo_dicts中。接下来,我们打印repo_dicts 的长度,以获悉我们获得了多少个仓库的信息。 为更深入地了解返回的有关每个仓库的信息,我们提取了repo_dicts中的第一个字典,并将 其存储在repo_dict中(见3)。接下来,我们打印这个字典包含的键数,看看其中有多少信息(见 4)。在5处,我们打印这个字典的所有键,看看其中包含哪些信息。 输出让我们对实际包含的数据有了更清晰的认识:
Status code: 200 Total repositories: 713062 Repositories returned: 30 1 Keys: 68 archive_url assignees_url blobs_url --snip-- url watchers watchers_count