用python爬取王者荣耀官网的英雄皮肤海报(含源码)

王者荣耀这款游戏有非常多的英雄,每个英雄又会有自己的皮肤,而在王者荣耀的官网,每个英雄皮肤都会有自己的高清海报,这篇文章会教大家如何用python爬虫的方法,将这些皮肤海报下载下来。

注:最新的代码在文章底部

爬虫路径探索

首先先看一下我们要爬取的目标,在每个英雄的详情页的顶部会有一个皮肤海报的展示区域。
下图为:王者荣耀官网西施的英雄信息页
在这里插入图片描述

给我们的爬虫一个起点

不难发现,我们要让爬虫可以获取到所有英雄的详情页的链接,可以把爬虫的起点设为王者荣耀官网-英雄资料页,从这个网页很容易获取到每个英雄的详情页。
我们是通过点击英雄头像进入英雄详情页的,通过浏览器的检查功能,可以看到:盘古的头像对应的超链接如下:
在这里插入图片描述

<a href="herodetail/529.shtml" target="_blank">
<img src="//game.gtimg.cn/images/yxzj/img201606/heroimg/529/529.jpg" width="91" height="91" alt="盘古">
盘古
</a>

a标签中的herf是超链接要跳转的网页地址,img标签中的src是头像的资源地址,访问资源地址可以将图片保存下来,而我们要找的就是皮肤图片对应的src。
不难发现img尾部的三位数字对应了超链接尾部的三位数字,可以理解为英雄id。
通过下面的方法可以获取到该页面所有的英雄头像的img标签,获取英雄id,和名字,再通过英雄id经过字符串处理获得英雄详情页的url,方法如下:

import requests
from bs4 import BeautifulSoup

url = "https://pvp.qq.com/web201605/herolist.shtml"
resp = requests.get(url)
resp.encoding = "GBK"
soup = BeautifulSoup(resp.text,'lxml')
alldiv = soup.find_all('img', width = '91')
for i in alldiv:
    print(i)
#输出:
#<img alt="云中君" height="91" src="//game.gtimg.cn/images/yxzj/img201606/heroimg/506/506.jpg" width="91"/>
#<img alt="瑶" height="91" src="//game.gtimg.cn/images/yxzj/img201606/heroimg/505/505.jpg" width="91"/>
#…………………………………………很多很多行
	name = i['alt']
	print(name,end=" ")
#输出:
#云中君 瑶 盘古 猪八戒 嫦娥 上官婉儿 李信 沈梦溪 伽罗 盾山 司马懿 孙策 元歌 米莱狄 狂铁 弈星 裴擒虎 杨玉环 公孙离 明世隐 女娲 梦奇 苏烈 百里玄策 百里守约 铠 鬼谷子 干将莫邪 东皇太一 大乔 黄忠 诸葛亮 哪吒 太乙真人 蔡文姬 雅典娜 杨戬 成吉思汗 锺馗 虞姬 李元芳 张飞 刘备 后羿 牛魔 孙悟空 亚瑟 橘右京 娜可露露 不知火舞 张良 花木兰 兰陵王 王昭君 韩信 刘邦 姜子牙 露娜 程咬金 安琪拉 貂蝉 关羽 老夫子 武则天 项羽 达摩 狄仁杰 马可波罗 李白 宫本武藏 典韦 曹操 甄姬 夏侯惇 周瑜 吕布 芈月 白起 扁鹊 孙膑 钟无艳 阿轲 高渐离 刘禅 庄周 鲁班七号 孙尚香 嬴政 妲己 墨子 赵云 小乔 廉颇 
	_id = i['src'].split('.')[0][-3:]
	url = "https://pvp.qq.com/web201605/herodetail/%s.shtml"%_id
	print(url)
#输出
#https://pvp.qq.com/web201605/herodetail/506.shtml
#https://pvp.qq.com/web201605/herodetail/505.shtml
#https://pvp.qq.com/web201605/herodetail/529.shtml
#https://pvp.qq.com/web201605/herodetail/511.shtml
#https://pvp.qq.com/web201605/herodetail/515.shtml
#…………………………………………很多很多行

这样我们就可以获取到了所有英雄的英雄详情页的url了。接下来探索怎么从英雄详情页找到皮肤名字和皮肤海报的src:

在这里插入图片描述
通过浏览器的检查功能发现,背景图再切换的时候div标签中的background中的资源链接发生了小许的变换
在这里插入图片描述
在这里插入图片描述
很容易知道,这个url就是我们找的皮肤海报的src,不信试试打开:
http://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/523/523-bigskin-1.jpg

http://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/523/523-bigskin-2.jpg

多看两个网页就会发现该链接的规则:http://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/523/523-bigskin-1.jpg
前面两个523是英雄编号,后面那个1是对应皮肤的编号(看那个英雄有几个皮肤,编号依次是1,2,3,4,5,6,7……n)。
然后我们尝试找的英雄的皮肤数量与名字,在检查工具中发现有这个标签。我们可以通过这个标签获取皮肤名字,当然知道名字的数量就知道有皮肤的数量了(可以退出编号的n)。
在这里插入图片描述
方法如下:

import requests
from bs4 import BeautifulSoup

url = "https://pvp.qq.com/web201605/herolist.shtml"
resp = requests.get(url)
resp.encoding = "gbk"
soup = BeautifulSoup(resp.text,'lxml')
alldiv = soup.find_all('img', width = '91')
for i in alldiv:
    _id = i['src'].split('.')[-2][-3:]
    url = "https://pvp.qq.com/web201605/herodetail/%s.shtml"%_id
    resp1 = requests.get(url)
    resp1.encoding  ='gbk'
    soup1 = BeautifulSoup(resp1.text, 'lxml')
    ul = soup1.find('ul',class_="pic-pf-list pic-pf-list3")
    names = ul['data-imgname']
    print("%s"%names)
# 输出(这是注释了下面输出语句的结果):
#流云之翼|荷鲁斯之眼
#
#鹿灵守心&0|森&0
#
#破晓之神&0|创世神祝&0
#
#无忧猛士&0|年年有余&0
#
#寒月公主&0|露花倒影&0
#……………………………………………………很多很多行
    namelist = []
    for name in names.split('|'):
        namelist.append(name.split('&')[0])
    print(namelist)
    print()
#输出(这是注释了上面输出语句的结果)    
#['流云之翼', '荷鲁斯之眼']
#
#['鹿灵守心', '森']
#
#['破晓之神', '创世神祝']
#
#['无忧猛士', '年年有余']
#
#['寒月公主', '露花倒影']
#
#['惊鸿之笔', '修竹墨客', '梁祝']

然后通过代码把皮肤链接与英雄名字和皮肤名字对应起来就可以了

注:最新的代码在文章底部

代码解析

首先导入要用到的模块

import requests
from bs4 import BeautifulSoup

写一个GetSoup函数用来解析网页。
注意:这里设置了一个请求头信息,如果不设请求头信息就相当于对服务器说:“嘿!我是个爬虫,你愿意把数据给我吗?”
对于很多的服务器其实是拒绝爬虫的,因为爬虫一般会大量的请求数据,给服务器造成压力,所以服务器更倾向于为真人服务。所以我们给我们的爬虫设请求头就是相当于对服务器撒一个小谎,说:“嘿?我是什么什么浏览器!快把数据发过来。”
对于一般的网站设了user-agent就足以蒙混过关了,但是对于有些网站就要伪装的更好一些(具体情况具体分析),在浏览器的开发者工具中找到复制过去就好了

headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                         'Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5958.400 SLBrowser/10.0.3533.400'}


def GetSoup(url):
    resp = requests.get(url, headers=headers)
    resp.encoding = 'gbk'
    soup = BeautifulSoup(resp.text, 'lxml')
    return soup

按照上面的步骤,逐个访问每个英雄详情页,获取英雄名字-皮肤名字和皮肤图片

url='https://pvp.qq.com/web201605/herolist.shtml'
soup = GetSoup(url)
#通过soup找到所有的英雄头像的<img>标签,
alldiv = soup.find_all('img', width='91')
for div in alldiv:
    # 通过<img>标签中的信息获取 英雄Id,英雄名字
    # Get id
    _id = div['src'][46:49]
    # Get hero_name
    hero_name = div['alt']
    
    # 获取每个英雄的皮肤的名字与皮肤图片的下载链接
    # Get skin-name
    url = 'https://pvp.qq.com/web201605/herodetail/%s.shtml' % _id
    soup = GetSoup(url)
    alldiv = soup.find('ul', class_='pic-pf-list pic-pf-list3')
    names = str(alldiv['data-imgname']).split('|')
    for i in range(len(names)):
        names[i]=names[i].split('&')[0]
    for i in range(len(names)):
        url5 = 'https://game.gtimg.cn/images/yxzj/img201606/heroimg/%s/%s-mobileskin-%s.jpg' % (_id, _id, i+1)
        resp5= requests.get(url5)
        print('正在下载%s-%s.jpg......... ' % (hero_name, names[i]))
        f = open('C:/Users/TTODS/Desktop/王者荣耀/英雄皮肤/%s-%s.jpg' % (hero_name, names[i]), 'wb')
        f.write(resp5.content)

爬取结果:

在这里插入图片描述

最新方法

经过测试发现上述方法无法成功获取到最新英雄的信息,原因是在云中君之后新出的英雄的头像图片并没有直接写在html文件中,而是采用了动态加载的方法。
在这里插入图片描述
打开开发者工具,可以发现Network中浏览器请求了个herolist.json文件,这里由于编码问题预览出现了乱码,通过json格式化工具可以发现里面存放的就是英雄信息。这就是动态加载的方法,浏览器先请求一个json文件,在通过服务器返回的json文件,通过写好的js代码向html中加入相关的内容,这样就不要手写html了(省去了手动复制粘贴和改id的步骤,只要在json文件中新加一个数据就行),果然是个好方法。同理,我们也可以通过这个json文件,直接获取英雄编号、英雄名字、英雄皮肤的名字和数量,大大减少了爬取数据的步骤(省去了大量的网页数据获取)。
在这里插入图片描述
在这里插入图片描述

代码(更新后)

import requests
import json
from bs4 import BeautifulSoup



headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                         'Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5958.400 SLBrowser/10.0.3533.400'}


def getSoup(url):
    resp = requests.get(url, headers=headers)
    resp.encoding = 'gbk'
    soup = BeautifulSoup(resp.text, 'lxml')
    return soup

#获取json数据,尝试得知存在有英雄的SkinName信息缺失或不全的情况,至少笔者写本文时是这样,
#所以这里只取用json文件中英雄id和名字

#获取json数据,并解析成存有英雄id与名字的列表[[id,name],[id1,name1].......]
def jsonToHeroInfoList(jsonURL):
    resp  =requests.get(jsonURL)
    jsonData = json.loads(resp.text)
    heroInfoList = []
    for data in jsonData:
        hero_info =[]
        hero_info.append(data['ename'])
        hero_info.append(data['cname'])
        heroInfoList.append(hero_info)
    return heroInfoList



#通过存有英雄id与名字的列表[[id,name],[id1,name1].......],获取皮肤名字和图片的src
def getImgSrc(heroInfoList):
    skinSrcList=[]
    for heroInfo in heroInfoList:
        heroName = heroInfo[1]
        heroId = heroInfo[0]
        #通过英雄id,进入英雄详情页获取皮肤名字和src
        detailUrl = "https://pvp.qq.com/web201605/herodetail/%s.shtml"%heroId
        soup = getSoup(detailUrl)
        ul = soup.find('ul', class_="pic-pf-list pic-pf-list3")
        skinNames = ul['data-imgname'].split('|')
        for index in range(len(skinNames)):
            skinName =heroName+"-"+skinNames[index].split('&')[0]
            imgSrc  = "http://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/%s/%s-bigskin-%s.jpg"%(heroId,heroId,index+1)
            skinSrcList.append([skinName,imgSrc])
    return skinSrcList

#通过skinSrcList[[skinname,src],[skinname2,src2]...........]逐个下载图片
def downLoadImg(skinSrcList):
    for src in skinSrcList:
        skinName = src[0]
        src = src[1]
        resp  = requests.get(src) 
        f = open('C:/Users/TTODS/Desktop/王者荣耀/英雄皮肤/%s.jpg'%skinName , 'wb')
        print("正在下载: "+skinName+" .....")
        f.write(resp.content)
        f.close()

Json_url = "https://pvp.qq.com/web201605/js/herolist.json"
heroInfoList = jsonToHeroInfoList(Json_url)
Imgsrc = getImgSrc(heroInfoList) 
downLoadImg(Imgsrc)   

同理,我们可以爬取到王者荣耀官网的英雄头像,装备图片,英雄技能说明等信息,这里就不仔细写过程了,我会把源码分享在下面:

发布了17 篇原创文章 · 获赞 27 · 访问量 2633
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章