数据藏在json文件中,如何爬取---以王者荣耀官网为例
作者:互联网
此前写了一个爬虫基础案例---爬取王者荣耀英雄与技能介绍
python爬虫------王者荣耀英雄及技能爬取并保存信息到excelhttps://blog.csdn.net/knighthood2001/article/details/119514336?spm=1001.2014.3001.5501眼尖的人能发现,爬到的数据不完全(英雄缺少)。
import requests
import re
import pandas as pd
base_url = 'https://pvp.qq.com/web201605/herolist.shtml'
headers = {
'referer': 'https://pvp.qq.com/',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(base_url, headers=headers)
response.encoding = 'gbk'
r = response.text
# print(response.text)
# 输出的是网页的全部源代码
# 由于英雄的网址为无序,故使用re
wangzhi = re.compile(r'<a href="herodetail/(\d*).shtml" target="_blank"')
hero_xuhao_list = re.findall(wangzhi, r)
# print(hero_xuhao_list)
df = []
# 标题栏
columns = ['英雄', '被动', '技能1', '技能2', '技能3', '技能4']
for id in hero_xuhao_list:
detail_url = 'https://pvp.qq.com/web201605/herodetail/{}.shtml'.format(id)
# print(detail_url)
response1 = requests.get(detail_url, headers=headers)
response1.encoding = 'gbk'
# print(response1.text) # 获得具体网址的全部源代码
names = re.compile('<label>(.*?)</label>')
name = names.findall(response1.text)[0]
# 没有这个[0],会使得excel中的数据是['云中君'],即中文名外面还有引号和[]
skills = re.compile('<p class="skill-desc">(.*?)</p>', re.S)
skill = skills.findall(response1.text)
# print(skill)
beidong = skill[0]
# print(beidong)
jineng1 = skill[1]
jineng2 = skill[2]
jineng3 = skill[3]
jineng4 = skill[4]
b = df.append([name, beidong, jineng1, jineng2, jineng3, jineng4])
d = pd.DataFrame(df, columns=columns)
# index=False表示输出不显示索引值
d.to_excel("王者荣耀英雄与技能.xlsx", index=False)
这是链接里面的源代码,方便阅读。
一、网页源代码和elements的区别
1.例子
首先打开王者荣耀全部英雄所在的网址
右键,可以看到查看网页源代码和检查-审查元素选项。
查看网页源代码(下图为部分截图)
检查---elements
查看网页源代码和检查-审查元素的页面,看着好像相同,但是如果仔细数的话,你会发现查看网页源代码中缺少了云缨-曜的英雄相关信息。
2.原因
查看源代码:别人服务器发送到浏览器的原封不动的代码。
检查-审查元素:看到的就是最终的html代码。即:源代码 + 网页js渲染 。
所以查看网页源代码和检查-审查元素中的内容不一定是一样的。
而用requests模块爬取到的response.text其实是网页源代码中的内容,未被网页js渲染。
所以此前代码是根据网页源代码爬取的,存在数据的缺失。
二、解决方案
1.寻找数据存储文件
我们需要去寻找数据存在于哪个文件中,
经查找,我们发现王者荣耀英雄存储在herolist.json文件中。
2.处理json文件
herolist.json的网址是https://pvp.qq.com/web201605/js/herolist.json
网页中显示的是乱码格式,通过下面代码可以正常显示json中的中文
import requests
url = 'https://pvp.qq.com/web201605/js/herolist.json'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(url, headers=headers)
print(response.text)
herolist = json.loads(response.text)
通过json.loads()将其他类型的对象转为python对象,方便后续的处理。
注意load和loads的区别,loads()操作的是字符串,而load()操作的是文件流。
https://pvp.qq.com/web201605/herodetail/538.shtml
https://pvp.qq.com/web201605/herodetail/155.shtml
可以发现json文件中的ename的数字就是构成具体英雄网页的数字,因此我们需要ename,
ename = []
for item in herolist:
herolist_ename = item["ename"]
ename.append(herolist_ename)
这段代码的作用是遍历herolist,将里面ename的值存储到ename列表中。
上面一行是herolist的内容,下面一行是ename列表的内容。
三、爬取相关数据
爬取到ename后,就可以遍历它,构造url进行爬取,爬取的步骤与之前一致。
python爬虫------王者荣耀英雄及技能爬取并保存信息到excel
base_url = "https://pvp.qq.com/web201605/herodetail/{}.shtml"
df = []
# 标题栏
columns = ['英雄', '被动', '技能1', '技能2', '技能3', '技能4']
a = 1
for i in ename:
# print(i)
true_url = base_url.format(i)
r = requests.get(true_url, headers=headers)
r.encoding = "gbk"
names = re.compile('<label>(.*?)</label>')
name = names.findall(r.text)[0]
# 用来显示英雄个数
print(str(a) + name)
a += 1
# 没有这个[0],会使得excel中的数据是['云中君'],即中文名外面还有引号和[]
skills = re.compile('<p class="skill-desc">(.*?)</p>', re.S)
skill = skills.findall(r.text)
# 数据清洗
beid = skill[0]
beidong = beid.replace("被动:", "")
jineng1 = skill[1]
jineng2 = skill[2]
jineng3 = skill[3]
jineng4 = skill[4]
b = df.append([name, beidong, jineng1, jineng2, jineng3, jineng4])
d = pd.DataFrame(df, columns=columns)
# index=False表示输出不显示索引值
d.to_excel("王者荣耀英雄与技能.xlsx", index=False)
由于大部分英雄的被动文本中存在被动:,,而小部分没有这些内容,所以需要 beidong = beid.replace("被动:", "")这段代码进行数据整理。
四、全部代码展示
import requests
import json
import re
import pandas as pd
url = 'https://pvp.qq.com/web201605/js/herolist.json'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(url, headers=headers)
# print(response.text)
herolist = json.loads(response.text)
# print(herolist)
ename = []
for item in herolist:
herolist_ename = item["ename"]
ename.append(herolist_ename)
# print(ename)
base_url = "https://pvp.qq.com/web201605/herodetail/{}.shtml"
df = []
# 标题栏
columns = ['英雄', '被动', '技能1', '技能2', '技能3', '技能4']
a = 1
for i in ename:
# print(i)
true_url = base_url.format(i)
r = requests.get(true_url, headers=headers)
r.encoding = "gbk"
names = re.compile('<label>(.*?)</label>')
name = names.findall(r.text)[0]
# 用来显示英雄个数
print(str(a) + name)
a += 1
# 没有这个[0],会使得excel中的数据是['云中君'],即中文名外面还有引号和[]
skills = re.compile('<p class="skill-desc">(.*?)</p>', re.S)
skill = skills.findall(r.text)
# 数据清洗
beid = skill[0]
beidong = beid.replace("被动:", "")
jineng1 = skill[1]
jineng2 = skill[2]
jineng3 = skill[3]
jineng4 = skill[4]
b = df.append([name, beidong, jineng1, jineng2, jineng3, jineng4])
d = pd.DataFrame(df, columns=columns)
# index=False表示输出不显示索引值
d.to_excel("王者荣耀英雄与技能.xlsx", index=False)
五、结果展示
六、总结
对于数据藏在json文件中时,首先要找到相应的文件。接下来进行解析等一系列操作。
我试过lxml和bs4解析,结果发现步骤非常繁琐,lxml解析出来经常为[]。
因此还是老老实实用re吧
经过爬取我才发现王者荣耀有106个英雄,平时上号时我都不在意这些
标签:herolist,爬取,ename,url,为例,---,json,skill,源代码 来源: https://blog.csdn.net/knighthood2001/article/details/120449819