Python爬虫案例与实战:爬取某游戏Top100选手信息
在实际生活或工作当中,有时需要在网络上查找榜单排行榜之类的数据,如高考前有必要在网络上查找全国大学排名或者专业排名,为毕业生报考提供参考依据,为方便进行类似的数据分析研究,将网页的表格存储到本地是必需的,本章案例将展示使用Python爬虫工具,从在线网站爬取表格并保存成如 Excel或CSV文档等可以重复使用编辑的形式,从网页获取表格的方式多种多样,本案例会根据网页的元素和特性选择合适的方案来编写爬虫。本案例针对同一个目标网站,请求使用的是Python的 Requests库,解析时用了Python的两种不同解析方法—JSON 和 BeautifulSoup(BS4)进行讲解,存储方案使用 CSV。
2.1 JavaScript对象与JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON 成为理想的数据交换语言,这即易于人阅读和编写。同时也易于机器解析和生成,并有效地提升网络的传输效率。JSON 是JavaScript对象的字符串表示法,它使用文本表示一个JavaScript对象的信息,本质是一个字符串。任何支持的类型都可以通过JSON 来表示,如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型。
1.对象
对象在 JavaScript 中是使用花括号({})包裹起来的内容,数据结构为{keyl:valuel,key2:
value2,.}的键值对结构。在面向对象的语言中,key为对象的属性,value 为对应的值。键
名可以使用整数和字符串来表示。值的类型可以是任意类型。
2.数组
数组在JavaScript中是方括号([])包裏起来的内容,数据结构为[“java”,“javascript”,
“vb”,]的索引结构。在JavaScript中,数组是一种比较特殊的数据类型,它也可以像对象那样使用键值对,但还是索引使用得多。同样,值的类型可以是任意类型。
例如,用对象的方式表示一个人的个人信息:
tom = {
name: 'Jack',
age: '24',
stature: 170,
gender: 'man'
}
然后,可以用对象和数组并用的方式表示,比如多个人的个人信息用一个JavaScript对象表示。
data = [
{
name: 'Jack',
age: '24',
stature: 170,
gender: 'man'
},
{
name: 'Mike',
age: '23',
stature: 174,
gender: 'man'
}
]
这种方式下用数组的索引访问某一个对象,然后使用键值对的方式访问对象内的元素。
在 Python语言中,可以使用JSON库对 JSON 字符串解析得到JavaScript对象,同时利用 Python字典这一键值索引访问方式并存的数据结构来访问JavaScript对象存储的数据。
2.2爬取方案分析
本案例将从5E游戏平台上爬取某游戏 TOP 100的选手信息,一种方案是爬取用于表格显示的JSON 对象,这种方案的思路与代码量相对简单;另一种则是用 BeautifulSoup库分析网页HTML 文本的子节点内容获取表格元素。
2.2.1方案一
1.网页分析
在5E平台网页打开开发者模式,如果网页表格通过JSON 存储数据,则在Network 栏选中XHR项进行抓包;如果Preview 一栏的元素符合JSON 格式,则可以使用JSON方式对网页列表进行抓取。JSON 对象的预览如图2-1所示。然后分析得出获取JSON 对象的请求方式为GET请求,如图2-2所示,容易分析得到GET请求的主机网站以及各项参数,有了以上分析即可编写爬虫程序。
[提示]从本案例用于发送请求的网址的域名可以看出,该域名是平台的API,如果从网站提供的API获取数据,通常都会返回JSON对象。
2.爬虫编写
main()函数:发送请求,获取JSON 对象。
import json
import requests
if __name__ == '__main__':
url = 'https://www.5ewin.com/api/data/rank'
query = {'scope': 'all', 'field': '', 'yyyy': '2000',
'season': '1', 'page': '1', 'region_id': ''}
# 发送GET请求用的参数
r = requests.get(url, params=query)
rank_list = json.loads(r.content, encoding='utf-8')
# 使用json.loads()函数将网页返回的JSON字符串加载为可以键值索引访问的JS对象
for i in range(100):
data = rank_list['data'][i]
print(data['rank_id'], data['username'], data['elo'])
'''
分析JS对象的键值,可以直接在终端上输出以查看结果
'''
3.输出结果
终端显示的是表格爬取的输出结果,如下。
1 bulu布鹿 3309.61
2 dyin林小衫 3298.22
3 Nero`斗鱼9348073 3219.5
4 抖音一凡 3216.44
5 抖音darkk 3215.87
6 京奈 3213.8
7 我叫弹幕大神 3201.07
8 怦怦a 3198.54
9 没灵感 3190.12
10 backway123- 3189.4
11 赖科旭 3185.93
12 ATTACKER23 3170.09
13 yubovo 3169.14
14 Start` 3168.51
15 k5t1- 3155.84
16 我就是大王滋滋崩 3151.76
2.2.2方案二
1.网页HTML 文本分析
下面针对第二种方案,先分析网页的HTML 文本的节点,找到表格每个玩家用户的信息,如图2-4所示,表格的每一栏位于子节点,然后一栏当中玩家用户的各项信息位于节点的各个子节点中,根据这个思路,只需要对请求到的网页返回内容进行解析,结合节点标签获取需要的信息并保存下来。
2.爬虫编写
爬虫代码分为main()函数部分、下载解析网页、网页内容存储,其中 main()函数为整个程序的入口,下面分别展示三部分代码。
(1)main()函数部分。
import requests
from bs4 import BeautifulSoup
import csv
if __name__ == '__main__':
URL = 'https://www.5ewin.com/data'
html = requests.get(URL)
soup = BeautifulSoup(html.content, 'html.parser')
topList = getTopList(soup)
# 从HTML文本解析结果中得到列表
writeTable(topList)
# 将列表进行本地csv文件的读写
(2)获取信息列表用于写入。
def getTopList(soup):
'''
函数说明:从HTML文本解析结果获取子节点内容,做成玩家信息的列表
Parameters:soup, HTML经BeautifulSoup库解析结果
Returns:topList, 用于输出的玩家信息列表
'''
top = soup.find_all('tr')
# 信息位于tr子节点
topList = []
for i in range(1, 101):
info = [i]
# info作为每一位玩家的信息列表
info.append(top[i].a.string)
# 用户名位于节点的<a>子节点的文本
country = top[i].i['class']
if len(country) > 1:
info.append(country[1].upper())
else:
info.append('Unknown')
# 用户所在国家地区位于节点的<i>子节点的标签
for node in top[i].find_all('td'):
'''
由网页分析,若只爬取玩家的天梯分数,
<tr>节点的<td>只有天梯分一栏标签非空
'''
if node.get('title') != None:
info.append(node.string)
topList.append(info)
return topList
(3)将信息写人本地 CSV文件。
def writeTable(List):
path = 'C:\\Users\\Asus\\Desktop\\文档\\5eplayTop100.csv'
with open(path, 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.writer(f)
# 引用csv库创建一个读写对象
writer.writerow(['排名', '玩家', '国家(地区)', ' 天梯分'])
# csv的文件头行标注各栏属性
3.输出结果:本地写入文件预览
将表格写入本地 CSV文件的输出结果如图2-5所示。
2.3本章小结
本章案例通过一个简单的网站榜单的爬取,介绍了最基本的爬虫步骤及工具,通过网站分析、请求、解析,存储为CSV文件,将爬虫常见的步骤都做了简单的示例,为读者进一步学习爬虫相关知识提供了基本的素材。