用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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章