Python爬虫:2022北京冬奥会奖牌榜

Author Avatar
白日鸡生蛋 2月5日
  • 在其它设备中阅读本文章

前言
2022 北京冬奥会已经开幕。除看比赛外,我也很关注奖牌榜。于是我就想着能不能自己做一个奖牌榜。

抓包分析
1 打开一个能看奥运会奖牌榜的网站
  我用到的是这个网站:https://2022.cctv.com/medal_list/,在浏览器中访问它。
2 找到数据源
  虽然说访问这个网站已经可以获得奖牌榜的相关数据了,但是这个页面太大了,处理起来非常不方便,于是我们要继续深入挖掘,找到直接的数据源。打开这个网站后,按下 F12 进入审查元素页面,选择“网络”(network)一栏,刷新网页。此时我们就可以获得很多资源,如图所示。
8bf7261198f83bcd0846ab650ed1376.png
  因为我们要找的不是图片,所以可以直接忽略图片类型资源,看到可疑的资源就点开看看。最终被我找到了,这是一条 json 数据,如图:
c7fd6327f3e34565a96621ea666f480.png
  查看请求头,记住这是 GET 方法
5ed59b1c87b3a32ede630230aab77f5.png

编写 Python 代码
1 测试链接是否正常

import requests

# 链接url
url = 'https://api.cntv.cn/olympic/getBjOlyMedals?serviceId=2022dongao&itemcode=GEN-------------------------------&t=jsonp&cb=omedals1'

# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.0.0 Safari/537.36',
}

if __name__ == '__main__':
    request = requests.get(url, headers=headers) # 请求链接,获得返回值
    print(request.text)

2 处理数据并输出

if __name__ == '__main__':
    json = requests.get(url, headers=headers).json() # 请求链接,获得返回值,转为json数据
    result = json['data']['medalsList']  # 获得该json数据中的,date列下的medalsList列下的数组
    # 输出
    for r in result:
        print(r['rank'],
              r['countryname'].ljust(7, ' '),
              '金' + r['gold'],
              '银' + r['silver'],
              '铜' + r['bronze'],
              '总' + r['count'])

  运行出错了。错误是JSONDecodeError,意思就是将 requstes 得到的数据转为 json 时发现它不符合 json 格式。再仔细看一下得到的数据:

omedals1({"data":{"total":13,"medalsList":[...]}});

  发现omedals1();是多余的,把它去掉就可以了。最终的代码:

import requests
import json

# 链接url
url = 'https://api.cntv.cn/olympic/getBjOlyMedals?serviceId=2022dongao&itemcode=GEN-------------------------------&t=jsonp&cb=omedals1'

# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.0.0 Safari/537.36',
}

if __name__ == '__main__':
    text = requests.get(url, headers=headers).text.strip('omedals1(').strip(');') #用.text方法将request转换为字符串。用strip去掉前后两块东西,因为它们不是json格式中的东西
    json = json.loads(text) #将字符串转换为json
    #下面是对json的处理
    result = json['data']['medalsList'] # 获得该json数据中的,date列下的medalsList列下的数组
    # 输出
    for r in result:
        print(r['rank'].ljust(2),
              r['countryname'].ljust(7, ' '),
              '金' + r['gold'],
              '银' + r['silver'],
              '铜' + r['bronze'],
              '总' + r['count'])

  运行测试:

1   挪威      金2 银0 铜0 总2
2   斯洛文尼亚   金1 银0 铜1 总2
3   荷兰      金1 银0 铜0 总1
3   瑞典      金1 银0 铜0 总1
3   中国      金1 银0 铜0 总1
6   意大利     金0 银2 铜0 总2
7   俄罗斯奥运队  金0 银1 铜1 总2
7   加拿大     金0 银1 铜1 总2
9   法国      金0 银1 铜0 总1
9   德国      金0 银1 铜0 总1
11  奥地利     金0 银0 铜1 总1
11  日本      金0 银0 铜1 总1
11  匈牙利     金0 银0 铜1 总1