2020东京奥运会金牌榜爬虫

页面分析

寻找Ajax接口

接口地址:https://api.cntv.cn/olympic/getOlyMedals?serviceId=pcocean&itemcode=GEN-------------------------------&t=jsonp&cb=omedals1

尝试请求接口,看是否能直接获取到数据

获取数据

伪造请求

1
2
3
url="https://api.cntv.cn/olympic/getOlyMedals?serviceId=pcocean&itemcode=GEN-------------------------------&t=jsonp&cb=omedals1"
data = requests.get(url=url).text
print(data)

数据清洗

将获取到的数据转化为JSON格式

将直接获取到的数据用json.loads函数报错,把数据放到JSON校验中查看并在代码中用正则处理

分析得出:数据多了omedals1,用正则处理掉

1
2
data = re.sub("omedals1\(",'',data)
data = re.sub("\);",'',data)

将处理后的数据转为JSON格式

1
jData = json.loads(data)

可以看到,现在输出的数据为字典与列表的结合,说明转码成功

将数据定位到奖牌

1
MedalList = jData['data']['medalsList']

分类

1
2
3
4
5
6
rank = i['rank']
countryname = i['countryname']
gold = i['gold']
silver = i['silver']
bronze = i['bronze']
count = i['count']

开始拼接字符串

1
2
ItemText = '排名:'+ rank + '\t' + countryname + '\t金牌:' + gold + '\t银牌:' + silver + '\t铜牌' + bronze + '\t总数:' + count + '\n'
String += ItemText

保存

1
2
3
4
5
6
7
8
with open('奖牌榜.csv', 'a', encoding="utf-8", newline='') as f:
header = ['排名', '国家', '金牌', '银牌', '铜牌', '总数']
f_csv = csv.writer(f)
f_csv.writerow(header)

with open('奖牌榜.csv', 'a', encoding="utf-8", newline='') as f:
f_csv = csv.writer(f)
f_csv.writerow(Csvitem)

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
2020东京奥运会金牌榜
排名:1 中国 金牌:38 银牌:29 铜牌17 总数:84
排名:2 美国 金牌:33 银牌:36 铜牌32 总数:101
排名:3 日本 金牌:24 银牌:12 铜牌16 总数:52
排名:4 英国 金牌:19 银牌:20 铜牌21 总数:60
排名:5 俄罗斯奥运队 金牌:17 银牌:24 铜牌22 总数:63
排名:6 澳大利亚 金牌:17 银牌:6 铜牌21 总数:44
排名:7 德国 金牌:10 银牌:11 铜牌16 总数:37
排名:8 意大利 金牌:10 银牌:10 铜牌18 总数:38
排名:9 荷兰 金牌:9 银牌:10 铜牌12 总数:31
排名:10 法国 金牌:7 银牌:12 铜牌9 总数:28
排名:11 新西兰 金牌:7 银牌:6 铜牌7 总数:20
排名:12 匈牙利 金牌:6 银牌:7 铜牌6 总数:19
排名:13 加拿大 金牌:6 银牌:6 铜牌11 总数:23
排名:14 韩国 金牌:6 银牌:4 铜牌9 总数:19
排名:15 巴西 金牌:6 银牌:4 铜牌8 总数:18
排名:16 古巴 金牌:6 银牌:3 铜牌4 总数:13
排名:17 波兰 金牌:4 银牌:4 铜牌5 总数:13
排名:18 捷克 金牌:4 银牌:3 铜牌2 总数:9
排名:19 牙买加 金牌:4 银牌:1 铜牌3 总数:8
排名:20 西班牙 金牌:3 银牌:6 铜牌5 总数:14
排名:21 瑞士 金牌:3 银牌:4 铜牌6 总数:13
排名:22 克罗地亚 金牌:3 银牌:3 铜牌2 总数:8
排名:22 肯尼亚 金牌:3 银牌:3 铜牌2 总数:8
排名:24 挪威 金牌:3 银牌:2 铜牌1 总数:6
排名:25 比利时 金牌:3 银牌:1 铜牌1 总数:5
排名:25 斯洛文尼亚 金牌:3 银牌:1 铜牌1 总数:5
排名:27 瑞典 金牌:2 银牌:6 铜牌0 总数:8
排名:28 格鲁吉亚 金牌:2 银牌:5 铜牌1 总数:8
排名:29 中国台北 金牌:2 银牌:4 铜牌6 总数:12
排名:30 丹麦 金牌:2 银牌:3 铜牌4 总数:9
排名:31 土耳其 金牌:2 银牌:2 铜牌8 总数:12
排名:32 伊朗 金牌:2 银牌:2 铜牌2 总数:6
排名:33 塞尔维亚 金牌:2 银牌:1 铜牌4 总数:7
排名:34 保加利亚 金牌:2 银牌:1 铜牌2 总数:5
排名:35 乌干达 金牌:2 银牌:1 铜牌1 总数:4
排名:36 厄瓜多尔 金牌:2 银牌:1 铜牌0 总数:3
排名:37 乌兹别克斯坦 金牌:2 银牌:0 铜牌2 总数:4
排名:38 希腊 金牌:2 银牌:0 铜牌1 总数:3
排名:38 卡塔尔 金牌:2 银牌:0 铜牌1 总数:3
排名:40 科索沃 金牌:2 银牌:0 铜牌0 总数:2
排名:40 巴哈马 金牌:2 银牌:0 铜牌0 总数:2
排名:42 乌克兰 金牌:1 银牌:5 铜牌10 总数:16
排名:43 白俄罗斯 金牌:1 银牌:3 铜牌2 总数:6
排名:44 罗马尼亚 金牌:1 银牌:3 铜牌0 总数:4
排名:44 委内瑞拉 金牌:1 银牌:3 铜牌0 总数:4
排名:46 中国香港 金牌:1 银牌:2 铜牌2 总数:5
排名:47 菲律宾 金牌:1 银牌:2 铜牌1 总数:4
排名:47 斯洛伐克 金牌:1 银牌:2 铜牌1 总数:4
排名:49 南非 金牌:1 银牌:2 铜牌0 总数:3
排名:50 奥地利 金牌:1 银牌:1 铜牌5 总数:7
排名:51 印度尼西亚 金牌:1 银牌:1 铜牌3 总数:5
排名:52 葡萄牙 金牌:1 银牌:1 铜牌2 总数:4
排名:53 埃塞俄比亚 金牌:1 银牌:1 铜牌1 总数:3
排名:54 突尼斯 金牌:1 银牌:1 铜牌0 总数:2
排名:55 以色列 金牌:1 银牌:0 铜牌2 总数:3
排名:55 爱尔兰 金牌:1 银牌:0 铜牌2 总数:3
排名:57 爱沙尼亚 金牌:1 银牌:0 铜牌1 总数:2
排名:57 泰国 金牌:1 银牌:0 铜牌1 总数:2
排名:57 斐济 金牌:1 银牌:0 铜牌1 总数:2
排名:57 拉脱维亚 金牌:1 银牌:0 铜牌1 总数:2
排名:61 百慕大 金牌:1 银牌:0 铜牌0 总数:1
排名:61 波多黎各 金牌:1 银牌:0 铜牌0 总数:1
排名:61 摩洛哥 金牌:1 银牌:0 铜牌0 总数:1
排名:64 哥伦比亚 金牌:0 银牌:4 铜牌1 总数:5
排名:65 多米尼加 金牌:0 银牌:3 铜牌2 总数:5
排名:66 印度 金牌:0 银牌:2 铜牌3 总数:5
排名:67 亚美尼亚 金牌:0 银牌:2 铜牌2 总数:4
排名:68 吉尔吉斯斯坦 金牌:0 银牌:2 铜牌1 总数:3
排名:69 蒙古 金牌:0 银牌:1 铜牌3 总数:4
排名:69 阿塞拜疆 金牌:0 银牌:1 铜牌3 总数:4
排名:71 阿根廷 金牌:0 银牌:1 铜牌2 总数:3
排名:71 圣马力诺 金牌:0 银牌:1 铜牌2 总数:3
排名:73 约旦 金牌:0 银牌:1 铜牌1 总数:2
排名:73 尼日利亚 金牌:0 银牌:1 铜牌1 总数:2
排名:75 土库曼斯坦 金牌:0 银牌:1 铜牌0 总数:1
排名:75 北马其顿 金牌:0 银牌:1 铜牌0 总数:1
排名:75 纳米比亚 金牌:0 银牌:1 铜牌0 总数:1
排名:75 立陶宛 金牌:0 银牌:1 铜牌0 总数:1
排名:79 哈萨克斯坦 金牌:0 银牌:0 铜牌7 总数:7
排名:80 墨西哥 金牌:0 银牌:0 铜牌4 总数:4
排名:80 埃及 金牌:0 银牌:0 铜牌4 总数:4
排名:82 芬兰 金牌:0 银牌:0 铜牌2 总数:2
排名:83 科威特 金牌:0 银牌:0 铜牌1 总数:1
排名:83 科特迪瓦 金牌:0 银牌:0 铜牌1 总数:1
排名:83 马来西亚 金牌:0 银牌:0 铜牌1 总数:1
排名:83 加纳 金牌:0 银牌:0 铜牌1 总数:1
排名:83 叙利亚 金牌:0 银牌:0 铜牌1 总数:1
排名:83 布基纳法索 金牌:0 银牌:0 铜牌1 总数:1
排名:83 格林纳达 金牌:0 银牌:0 铜牌1 总数:1
排名:83 摩尔多瓦 金牌:0 银牌:0 铜牌1 总数:1


进程已结束,退出代码为 0

可视化

数据处理

声明x轴y轴的数据

1
2
3
4
5
6
7
8
9
10
tGold = []
tSilver = []
tBronze = []
tCountryName = []

for i in Medallist:
tGold.append(i['gold'])
tSilver.append(i['silver'])
tBronze.append(i['bronze'])
tCountryName.append(i['countryname'])

调用Pyecharts 生成条形图

1
2
3
4
5
6
7
8
9
10
11
12
13
c = (
Bar(init_opts=opts.InitOpts(width='1440px',height='2000px'))
.add_yaxis("金牌", tGold, stack="stack1")
.add_yaxis("银牌", tSilver, stack="stack1")
.add_yaxis("铜牌", tBronze, stack="stack1")
.add_xaxis(tCountryName)
.reversal_axis()
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(title_opts=opts.TitleOpts(title="2020东京奥运奖牌榜"),
yaxis_opts=opts.AxisOpts(is_inverse=True)
)
)
c.render("MedalList.html")

全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import requests,json,re,csv
from pyecharts import options as opts
from pyecharts.charts import Bar



def spyder():
url ="https://api.cntv.cn/olympic/getOlyMedals?serviceId=pcocean&itemcode=GEN-------------------------------&t=jsonp&cb=banomedals"
data = requests.get(url=url).text
data = re.sub('omedals1\(','',data)
data = re.sub('\);','',data)
jData = json.loads(data)
MedalsList = jData['data']['medalsList']
String = '奥运奖牌榜\n'
with open('奖牌榜.csv', 'a', encoding="utf-8", newline='') as f:
header = ['排名', '国家', '金牌', '银牌', '铜牌', '总数']
f_csv = csv.writer(f)
f_csv.writerow(header)

for i in MedalsList:
rank = i['rank']
count = i['count']
gold = i['gold']
silver = i['silver']
bronze = i['bronze']
countryname = i['countryname']

Csvitem = []
Csvitem.append(rank)
Csvitem.append(countryname)
Csvitem.append(count)
Csvitem.append(gold)
Csvitem.append(silver)
Csvitem.append(bronze)
String += '排名:'+ rank + '\t' + countryname + '\t金牌:' + gold + '\t银牌:' + silver + '\t铜牌' + bronze + '\t总数:' + count + '\n'
#print(String)

with open('奖牌榜.csv', 'a', encoding="utf-8", newline='') as f:
f_csv = csv.writer(f)
f_csv.writerow(Csvitem)
return MedalsList

# 可视化

def drow(medalslist):
tGold = []
tSilver = []
tBronze = []
tCountryName = []

for i in medalslist:
tGold.append(i['gold'])
tSilver.append(i['silver'])
tBronze.append(i['bronze'])
tCountryName.append(i['countryname'])

c = (
Bar(init_opts=opts.InitOpts(width='1440px', height='2000px'))
.add_yaxis("金牌", tGold, stack="stack1")
.add_yaxis("银牌", tSilver, stack="stack1")
.add_yaxis("铜牌", tBronze, stack="stack1")
.add_xaxis(tCountryName)
.reversal_axis()
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(title_opts=opts.TitleOpts(title="2020东京奥运奖牌榜"),
yaxis_opts=opts.AxisOpts(is_inverse=True)
)
)
c.render("MedalList.html")
print('ok')

if __name__ == '__main__':
drow(spyder())

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!