Skip to content

Commit 2bb57ec

Browse files
committed
十七章课后练习
1 parent 0e0f66b commit 2bb57ec

File tree

4 files changed

+217
-0
lines changed

4 files changed

+217
-0
lines changed

chapter17/17-1.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import requests
2+
import pygal
3+
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS
4+
5+
# Make an API call, and store the response.
6+
url = 'https://api.github.com/search/repositories?q=language:javascript&sort=stars'
7+
r = requests.get(url)
8+
print("Status code:", r.status_code)
9+
10+
# Store API response in a variable.
11+
response_dict = r.json()
12+
print("Total repositories:", response_dict['total_count'])
13+
14+
# Explore information about the repositories.
15+
repo_dicts = response_dict['items']
16+
17+
names, plot_dicts = [], []
18+
for repo_dict in repo_dicts:
19+
names.append(repo_dict['name'])
20+
21+
# When a project is removed, it's still listed with stars.
22+
# So it's in the top projects, but has no description. The description
23+
# is None, which causes an exception when being used as a label.
24+
if repo_dict['description']:
25+
desc = repo_dict['description']
26+
else:
27+
desc = 'No description provided.'
28+
29+
plot_dict = {
30+
'value': repo_dict['stargazers_count'],
31+
'label': desc,
32+
'xlink': repo_dict['html_url'],
33+
}
34+
plot_dicts.append(plot_dict)
35+
36+
# Make visualization.
37+
my_style = LS('#333366', base_style=LCS)
38+
my_style.title_font_size = 24
39+
my_style.label_font_size = 14
40+
my_style.major_label_font_size = 18
41+
42+
my_config = pygal.Config()
43+
my_config.x_label_rotation = 45
44+
my_config.show_legend = False
45+
my_config.truncate_label = 15
46+
my_config.show_y_guides = False
47+
my_config.width = 1000
48+
49+
chart = pygal.Bar(my_config, style=my_style)
50+
chart.title = 'Most-Starred JavaScript Projects on GitHub'
51+
chart.x_labels = names
52+
53+
chart.add('', plot_dicts)
54+
chart.render_to_file('js_repos.svg')

chapter17/17-2.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import requests
2+
import pygal
3+
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS
4+
5+
from operator import itemgetter
6+
7+
# Make an API call, and store the response.
8+
url = 'https://hacker-news.firebaseio.com/v0/topstories.json'
9+
r = requests.get(url)
10+
print("Status code:", r.status_code)
11+
12+
# Process information about each submission.
13+
submission_ids = r.json()
14+
submission_dicts = []
15+
for submission_id in submission_ids[:30]:
16+
# Make a separate API call for each submission.
17+
url = ('https://hacker-news.firebaseio.com/v0/item/' +
18+
str(submission_id) + '.json')
19+
submission_r = requests.get(url)
20+
print(submission_r.status_code)
21+
response_dict = submission_r.json()
22+
23+
submission_dict = {
24+
'title': response_dict['title'],
25+
'link': 'http://news.ycombinator.com/item?id=' + str(submission_id),
26+
'comments': response_dict.get('descendants', 0)
27+
}
28+
submission_dicts.append(submission_dict)
29+
30+
submission_dicts = sorted(submission_dicts, key=itemgetter('comments'),
31+
reverse=True)
32+
33+
for submission_dict in submission_dicts:
34+
print("\nTitle:", submission_dict['title'])
35+
print("Discussion link:", submission_dict['link'])
36+
print("Comments:", submission_dict['comments'])
37+
38+
titles, plot_dicts = [], []
39+
for submission_dict in submission_dicts:
40+
titles.append(submission_dict['title'])
41+
plot_dict = {
42+
'value': submission_dict['comments'],
43+
'label': submission_dict['title'],
44+
'xlink': submission_dict['link'],
45+
}
46+
plot_dicts.append(plot_dict)
47+
48+
# Make visualization.
49+
my_style = LS('#333366', base_style=LCS)
50+
my_style.title_font_size = 24
51+
my_style.label_font_size = 14
52+
my_style.major_label_font_size = 18
53+
54+
my_config = pygal.Config()
55+
my_config.x_label_rotation = 45
56+
my_config.show_legend = False
57+
my_config.truncate_label = 15
58+
my_config.show_y_guides = False
59+
my_config.width = 1000
60+
my_config.y_title = 'Number of Comments'
61+
62+
chart = pygal.Bar(my_config, style=my_style)
63+
chart.title = 'Most Active Discussions on Hacker News'
64+
chart.x_labels = titles
65+
66+
chart.add('', plot_dicts)
67+
chart.render_to_file('hn_discussions.svg')

chapter17/17-3.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import unittest
2+
3+
import python_repos_for_testing as pr
4+
5+
class PythonReposTestCase(unittest.TestCase):
6+
"""Tests for python_repos.py."""
7+
8+
def setUp(self):
9+
"""Call all the functions here, and test elements separately."""
10+
self.r = pr.get_response()
11+
self.repo_dicts = pr.get_repo_dicts(self.r)
12+
self.repo_dict = self.repo_dicts[0]
13+
self.names, self.plot_dicts = pr.get_names_plot_dicts(self.repo_dicts)
14+
15+
def test_get_response(self):
16+
"""Test that we get a valid response."""
17+
self.assertEqual(self.r.status_code, 200)
18+
19+
def test_repo_dicts(self):
20+
"""Test that we're getting the data we think we are."""
21+
# We should get dicts for 30 repositories.
22+
self.assertEqual(len(self.repo_dicts), 30)
23+
24+
# Repositories should have required keys.
25+
required_keys = ['name', 'owner', 'stargazers_count', 'html_url']
26+
for key in required_keys:
27+
self.assertTrue(key in self.repo_dict.keys())
28+
29+
unittest.main()

chapter17/python_repos.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import requests
2+
import pygal
3+
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS
4+
5+
from operator import itemgetter
6+
7+
# Make an API call, and store the response.
8+
url = 'https://hacker-news.firebaseio.com/v0/topstories.json'
9+
r = requests.get(url)
10+
print("Status code:", r.status_code)
11+
12+
# Process information about each submission.
13+
submission_ids = r.json()
14+
submission_dicts = []
15+
for submission_id in submission_ids[:30]:
16+
# Make a separate API call for each submission.
17+
url = ('https://hacker-news.firebaseio.com/v0/item/' +
18+
str(submission_id) + '.json')
19+
submission_r = requests.get(url)
20+
print(submission_r.status_code)
21+
response_dict = submission_r.json()
22+
23+
submission_dict = {
24+
'title': response_dict['title'],
25+
'link': 'http://news.ycombinator.com/item?id=' + str(submission_id),
26+
'comments': response_dict.get('descendants', 0)
27+
}
28+
submission_dicts.append(submission_dict)
29+
30+
submission_dicts = sorted(submission_dicts, key=itemgetter('comments'),
31+
reverse=True)
32+
33+
for submission_dict in submission_dicts:
34+
print("\nTitle:", submission_dict['title'])
35+
print("Discussion link:", submission_dict['link'])
36+
print("Comments:", submission_dict['comments'])
37+
38+
titles, plot_dicts = [], []
39+
for submission_dict in submission_dicts:
40+
titles.append(submission_dict['title'])
41+
plot_dict = {
42+
'value': submission_dict['comments'],
43+
'label': submission_dict['title'],
44+
'xlink': submission_dict['link'],
45+
}
46+
plot_dicts.append(plot_dict)
47+
48+
# Make visualization.
49+
my_style = LS('#333366', base_style=LCS)
50+
my_style.title_font_size = 24
51+
my_style.label_font_size = 14
52+
my_style.major_label_font_size = 18
53+
54+
my_config = pygal.Config()
55+
my_config.x_label_rotation = 45
56+
my_config.show_legend = False
57+
my_config.truncate_label = 15
58+
my_config.show_y_guides = False
59+
my_config.width = 1000
60+
my_config.y_title = 'Number of Comments'
61+
62+
chart = pygal.Bar(my_config, style=my_style)
63+
chart.title = 'Most Active Discussions on Hacker News'
64+
chart.x_labels = titles
65+
66+
chart.add('', plot_dicts)
67+
chart.render_to_file('hn_discussions.svg')

0 commit comments

Comments
 (0)