今天上午将昨天遗留的问题解决了。项目是通过GitHub的api来调用当前托管的最受欢迎Python项目的信息。调用地址是:https://api.github.com/search/repositories?q=language:python&sort=stars
首先使用requests来执行调用并返回json格式信息,然后将其转为字典来进行下一步处理:
import requests
url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
response_dict = r.json()
得到的字典包含了相关的信息,也可以通过直接访问地址来观察信息内容。字典内包含了三个key:items,total_count,incomplete_results。所关心的内容都在items中。items对应的value是一个列表,列表内的每个元素都是一个字典形式存储的仓库信息。具体的信息包括名称,所有者,星级,地址,描述等等。可以通过循环来获取这些信息。
为了方便下一步通过pygal进行可视化处理,我们分别用两个列表分别保存item中各个元素的name,stars。
repo_dicts = response_dict['item']
names,stars=[],[]
for repo_dict in repo_dicts:
names.append(repo_dict['name'])
stars.append(repo_dict['stargazers_count'])
进行可视化操作即将柱状图的x_labels设置为names,数据使用add('',stars)即可实现。
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 = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names
chart.add('', stars)
chart.render_to_file('python_repos.svg')
当然如此已经完成了基本任务,得到了一个图片,但是我们想要在每个python项目上显示相应的描述和链接地址。已经学到可以通过add('',dictLlist)来进行添加列表操作,不过要求列表的元素是一个字典,字典的key比如value存储数据,label存储描述,xlink描述链接,具体操作也有演示如下:
names, plot_dicts = [], []
for repo_dict in repo_dicts:
names.append(repo_dict['name'])
plot_dict = {
'value': repo_dict['stargazers_count'],
'label': repo_dict['description'],
'xlink': repo_dict['html_url'],}
plot_dicts.append(plot_dict)
最后chart.add('',plot_dicts)即可。
不过这一步出现了异常UnicodeDecodeError,异常描述是发现了'gbk'编码无法使用解码。我开始网络搜索,并不断尝试。开始时候由于api访问速率限制,每分钟十次,导致访问不到数据。我考虑能不能使用json来将数据保存在本地进行访问,然而在使用json.dump()的时候,仍旧出现编码问题。为什么编码出错,我简单理解是因为出现乱码,比如gbk编码而utf-8解码,但得到的信息是说,这种情况会乱码,但不会出错。不过有信息说可能与idle GUI有关,我使用命令行来执行也并没有得到改善。看来并不是这个问题。
这时候只好从信息本身来寻找答案,我打开api.guihub的链接,然后来观察items中的信息,发现与想象的问题并不相同,在有一行描述中居然出现了五角星以及笑脸标记。简直没办法吐糟作者是什么脑回路。那么问题已经找出来了,该怎么解决呢?编码问题我了解的不多。
第一个尝试是使用try-except-来跳过出错的描述。这样我确实得到了一个本地json文件,观察到可以得到数据,但问题是在异常字符位置之后就没有其他数据。而且考虑到使用异常处理,对于原有的信息是进行忽略处理,得到的json文件中也只有部分数据,我犹豫再三,决定从编码入手解决问题。
又回到异常描述上:
UnicodeDecodeError: ‘XXX' codec can't decode bytes in position
对于编码,我之前看到过一些,字符串拥有decode(),encode()函数操作。我怀疑获取的json并不是utf-8格式,然后直接使用repo_dict['description'].decode('utf-8'),但运行之后告诉我str没有decode属性,说明产生的字符串默认文本是unicode格式,不需要进行重新utf-8解码,即类型是
至于NoneType问题,我第一反应是可能有些元素没有description对应的value,这样就可以使用判断语句来进行操作,如果repo_dict['description']存在就使用decode()编码后,变成bytes类型,加入列表的字典元素,否则就直接用空字符串替代。
进行运行,发现在新创建json文件保存获得的数据时又出错。考虑到原来的版本中并没有将数据保存在本地,我先将其注释掉,结果顺利运行,得到了可视化的数据结果。而且笑脸符号和星星符号也得到正确显示。
那么json文件保存怎么处理呢?之后进行分析,发现json文件不能保存bytes类型,只能保持成常规的字符串。那么怎么解决,我们刚刚使用转换bytes类型将特殊字符的问题解决了,又回到这个问题上。需要重新编码呢?我换了一种思路,能不能将字典元素直接转换为字符串,而不保存在json文件,仅仅使用普通文件读写操作就可以把?果然如此,使用文本读写,操作,完全绕过了bytes格式无法写入json的问题,不过这样却没办法利用json对数据进行load()操作,不过我们事实上也不需要这个操作,于是问题已经完全解决。
with open('new.txt','w') as new:
for i in list(range(len(names))):
new.write(str(i)+'item:\n')
new.write(names[i]+':\n')
new.write('\t'+str(stars_plot_dicts[i])+'\n\n')
这次项目问题的解决,对于基础的要求足以体现,比如json文件存储的要求,以及复杂编码的问题等等。实际遇到的问题远远不同于概念学习。当然基础很重要,应用更重要。此外,互联网社区查找是一个很大的帮助,因为别人也可能和你遇到同样的问题。
晚上学习django建立一个web应用程序,虽然学会了构建平台,但具体的操作没办法完成,一个主要原因是django版本不同,很多函数运行出错,简单跟随书本没办法学习,只好放弃。当然这方面长远来看很重要,不过现阶段仍旧以数据分析为重点,下个月如果有时间对django进行系统的学习。