學習如何編寫一個獨立的程序,並對其進行可視化。
利用Web應用編程接口(API)自動請求網站的特定信息而不是整個網頁,再對信息進行可視化,這樣即使數據瞬息萬變,程序呈現的信息也是最新的。
API調用 : Web API是網站的一部分,用於與使用非常具體的URL請求特定信息的程序交互。請求得到的數據將以易於處理的格式(JOSN, CSV)返回。
實戰: 使用GitHub的API請求有關該網站中的python信息,使用Pygal生成交互可視化,呈現這些項目的受歡迎程度。
打開如下網址
https://api.github.com/search/repositories?q=language:python&sort=starts
這個調用返回GitHub當前托管了多少個python項目,還有有關最受歡迎的python倉庫的信息。
解釋調用:
https://api.github.com/ 將請求發送到GitHub網站中相應API調用的部分
search/repositories 搜索所有GitHub上的倉庫
q=q
表示查詢 =
指定查詢
language:python 使用語言為python的倉庫項目信息
&sort=starts 將項目按所獲得的星級排序
下面顯示了相應的前幾行。從響應可知,該URL並不適合人工輸入
“total_count”: 9070185, 寫該文章的時刻,GitHub共9070185個python項目
“incomplete_results”: true, 請求成功。true,GitHub無法全面處理該API;若為false,則代表請求並非完整
item 其中包含GitHub上最受歡迎的Python項目的詳細信息
requests包向網站請求信息並檢查返回的響應
先查看自己的conda環境
conda env list
激活要使用的環境
conda activate pythonProject
安裝requests包
pip install --user requests
編寫一個程序, 執行API調用,並處理結果,找出GitHub上星級最高的Python項目:
import requests
# 執行API調用並存儲響應
url = 'https://api.github.com/search/repositories?q=language:python&sort=starts'
# 將url傳遞給r,再將響應對象存儲在變量r中
r = requests.get(url)
# 通過查看響應對象的一個status_code屬性,知道了請求是否成功(狀態碼200表示請求成功)
print("Status code:", r.status_code)
# 將API響應存儲在一個變量中(將返回的json格式信息轉化為python字典)
response_dict = r.json()
# 處理結果,查看有哪些鍵值
print(response_dict.keys())
調用程序查看結果
python_repos.py
import requests
# 執行API調用並存儲響應
url = 'https://api.github.com/search/repositories?q=language:python&sort=starts'
# 將url傳遞給r,再將響應對象存儲在變量r中
r = requests.get(url)
# 通過查看響應對象的一個status_code屬性,知道了請求是否成功(狀態碼200表示請求成功)
print("Status code:", r.status_code)
# 將API響應存儲在一個變量中(將返回的json格式信息轉化為python字典)
response_dict = r.json()
print("Total repositories:", response_dict['total_count']) # 查看共有多少個倉庫
# 探索有關倉庫的信息
repo_dicts = response_dict['items'] # 每個與items相關的字典都包含一個有關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)
下面提取repo_dict中與一些鍵相關聯的值:
python_repos.py
--snip--
# 研究第一個倉庫
repo_dict = repo_dicts[0]
print("\nSelected information about first repository:")
print('Name:', repo_dict['name']) # 項目名稱
print('Owner:', repo_dict['owner']['login']) # ['owner']獲取項目所有者的字典 ['login']獲取項目所有者的登錄名
print('Stars:', repo_dict['stargazers_count']) # 獲得的star數
print('Repository:', repo_dict['html_url'])
print('Created:', repo_dict['created_at']) # 建庫時間
print('UPdate:', repo_dict['updated_at']) # 最近更新時間
print('Description:', repo_dict['description'])
寫文章此刻,最受歡迎的項目是system-design-primer
查看每一個倉庫的信息
python_repos.py
--snip--
# 研究有關倉庫的信息
print("\nSelected information about each repository:")
# 打印一條說明性的信息
for repo_dict in repo_dicts:
print('\nName:', repo_dict['name']) # 項目名稱
print('Owner:', repo_dict['owner']['login']) # ['owner']獲取項目所有者的字典 ['login']獲取項目所有者的登錄名
print('Stars:', repo_dict['stargazers_count']) # 獲得的star數
print('Repository:', repo_dict['html_url'])
print('Created:', repo_dict['created_at']) # 建庫時間
print('UPdate:', repo_dict['updated_at']) # 最近更新時間
print('Description:', repo_dict['description'])
大多數API都存在速率限制,即在特定時間內的可執行的請求數存在限制。
要獲悉自己是否接近了GitHub的限制,可以輸入如下網址查看
https://api.github.com/rate_limit
將看到如下響應
我們關心的信息是搜索API的速度限制
limit極限為每分鐘10個請求
remaining當前這一分鐘內還可再執行8個請求
reset配額將重置的時Unix時間或新紀元時間(1970年1月1日午夜後多少秒)
用完配額後,將收到一條簡單的響應,由此知道已達到API極限。到達極限後必須等待配額重置。
注意:很多API都要求注冊獲得API密鑰後才能執行API調用,GitHub沒有這樣的要求,但是獲得API密鑰後,配額將高得多。
python_repos.py
import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightStyle as LS
# 執行API調用並存儲響應
url = 'https://api.github.com/search/repositories?q=language:python&sort=starts'
# 將url傳遞給r,再將響應對象存儲在變量r中
r = requests.get(url)
# 通過查看響應對象的一個status_code屬性,知道了請求是否成功(狀態碼200表示請求成功)
print("Status code:", r.status_code)
# 將API響應存儲在一個變量中(將返回的json格式信息轉化為python字典)
response_dict = r.json()
print("Total repositories:", response_dict['total_count']) # 查看共有多少個倉庫
# 探索有關倉庫的信息
repo_dicts = response_dict['items'] # 每個與items相關的字典都包含一個有關python倉庫的信息
# print("Repositories returned:", len(repo_dicts)) # 查看得到了多少個倉庫的信息
names, stars = [], []
for repo_dict in repo_dicts:
names.append(repo_dict['name'])
stars.append(repo_dict['stargazers_count'])
# 可視化
my_style = LS # 使用LightenStyle類作為Bar的基本格式
chart = pygal.Bar(style=my_style, x_label_rotation=45, show_legend=False) #標簽繞x軸轉45度,並隱藏了圖例
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names
chart.add('', stars) # 添加數據時,將標簽設置為空字符串
chart.render_to_file('python_repos.svg')
用浏覽器打開生成的python_repos.svg
設置圖表標題,副標題和主標簽的字體大小
副標題: x軸上的項目名稱,以及y軸上的大部分數字
主標簽: y軸上5000的整數倍刻度
truncate_label: 將較長的項目名縮短為15個字符(如果將鼠標指向屏幕上被截短的項目名,將顯式完整的項目名)
show_y_guides: 設置為False,以隱藏圖表中的水平線
import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightStyle as LS
# 執行API調用並存儲響應
url = 'https://api.github.com/search/repositories?q=language:python&sort=starts'
# 將url傳遞給r,再將響應對象存儲在變量r中
r = requests.get(url)
# 通過查看響應對象的一個status_code屬性,知道了請求是否成功(狀態碼200表示請求成功)
print("Status code:", r.status_code)
# 將API響應存儲在一個變量中(將返回的json格式信息轉化為python字典)
response_dict = r.json()
print("Total repositories:", response_dict['total_count']) # 查看共有多少個倉庫
# 探索有關倉庫的信息
repo_dicts = response_dict['items'] # 每個與items相關的字典都包含一個有關python倉庫的信息
# print("Repositories returned:", len(repo_dicts)) # 查看得到了多少個倉庫的信息
names, stars = [], []
for repo_dict in repo_dicts:
names.append(repo_dict['name'])
stars.append(repo_dict['stargazers_count'])
# 可視化
my_style = LS # 使用LightenStyle類,並設置基調為藍色
my_config = pygal.Config() # 創建一個Pygal類Config的實例
my_config.x_label_rotation = 45
my_config.show_legend = True
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) #標簽繞x軸轉45度,並隱藏了圖例
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names
chart.add('', stars) # 添加數據時,將標簽設置為空字符串
chart.render_to_file('python_repos.svg')
my_config.show_legend = False
隱藏圖例
工具提示: 在Pygal中將鼠標指向條形,將顯示它表示的信息
下面創建一個自定義工具提示,以顯示項目的描述
bar_discriptions.py
import pygal
from pygal.style import LightColorizedStyle as LCS, LightStyle as LS
my_style = LS
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': 'Descripiton of django'},
{
'value': 14798, 'label': 'Description of flask'},
]
chart.add('', plot_dicts)
chart.render_to_file('bar_descriptions.svg')
自動生成plot_dicts,其中包含API返回的30個項目
python_repos.py
# 探索有關倉庫的信息
repo_dicts = response_dict['items'] # 每個與items相關的字典都包含一個有關python倉庫的信息
print("Number of items:", len(repo_dicts)) # 查看得到了多少個倉庫的信息
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']}
plot_dicts.append(plot_dict)
# 可視化
my_style = LCS # 使用LightenStyle類,並設置基調為藍色
--snip--
chart = pygal.Bar(my_config, style=my_style) #標簽繞x軸轉45度,並隱藏了圖例
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names
chart.add('', plot_dicts) # 添加數據時,將標簽設置為空字符串
chart.render_to_file('python_repos_bar_descriptions.svg')
Pygal允許將圖表中的每個條形用作網站的鏈接,只需要在為每個項目創建的字典中,添加一個鍵對‘xlink’:
python_repos.py
--snip--
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)
--snip--
此時打開圖表,再單擊每一個條形,都會在新的窗口中跳轉到對應github項目地址!
為探索如何使用其他網站的API調用,我們來看看Hacker News(http://news.ycombinator.com/)。
在Hacker News網站,用戶分享編程技巧方面的文章, 並就此展開積極的討論。Hacker News的API讓你能夠訪問有關該網站所有文章和評論的信息,且不要求你通過注冊獲得密鑰。
https://hacker-news.firebaseio.com/v0/item/9884165.json
響應是一個字典,包含ID為9884165的文章信息
import requests
from operator import itemgetter
# 執行API調用並存儲響應
url = 'https://hacker-news.firebaseio.com/v0/topstories.json'
r = requests.get(url) # 其中包含了Hacker News上當前最熱門的500片篇文章的ID
print("Status code", r.status_code)
# 處理有關每篇文章的信息
submission_ids = r.json()
submission_dicts = []
for submission_id in submission_ids[:30]:
# 對於每篇文章,都執行一個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),
'comments': response_dict.get('descendants', 0) #當評論數為0時,就沒有comments這一項
}
submission_dicts.append(submission_dict)
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'])
使用任何API來訪問和分析信息時,流程都與此類似。有了數據後,就可以進行數據可視化了。