30行Python代碼爬取英雄聯盟全英雄全皮膚

30行Python代碼爬取英雄聯盟全英雄全皮膚

碎碎念

英雄聯盟遊戲裏擁有數百個個性英雄,然後每個英雄都有多個皮膚。作爲一個收集控就非常想收齊全部皮膚----的圖片。家境貧寒一言難盡看官點個讚唄!

前期分析

英雄皮膚的圖鑑信息可以到官網遊戲資料(https://lol.qq.com/data/info-heros.shtml)查看到。

爬取皮膚本身難度不大,就是將數據以二進制形式保存到文件中。難點是怎麼拿到皮膚圖片的URL地址。馬上到官網,點開幾個英雄皮膚分析一下。

隨意選擇一位英雄,然後F12打開調試臺,找到英雄皮膚的圖片地址:

找到皮膚圖片位置,然後我們多找幾個皮膚圖片地址來對比分析,找到其中的規律:

英雄一
https://game.gtimg.cn/images/lol/act/img/skin/big1000.jpg
https://game.gtimg.cn/images/lol/act/img/skin/big1001.jpg
https://game.gtimg.cn/images/lol/act/img/skin/big1002.jpg
英雄二
https://game.gtimg.cn/images/lol/act/img/skin/big2000.jpg
https://game.gtimg.cn/images/lol/act/img/skin/big2001.jpg
https://game.gtimg.cn/images/lol/act/img/skin/big2002.jpg

這裏對比分析兩個英雄的3個皮膚圖片地址,發現只有最後的序號發生變換,猜測皮膚圖片的地址通用格式爲https://game.gtimg.cn/images/lol/act/img/skin/bigxxxx.jpg。序號部分規律應該是最前一位數字代表着英雄的編號,後三位的數字代表該英雄的皮膚編號。

x       xxx
英雄編號 皮膚編號

按照這個規律,我們就能將全部的英雄皮膚圖片地址推算出來。但。。。。實際上,英雄編號並不是依次遞增的。比如說新英雄瑟提的編號爲875,而實際上瑟提爲正式服的第148位英雄。

這樣一來,視乎英雄編號就沒有什麼規律了。別急,在英雄資料頁,打開F12調試臺,抓取網絡請求,發現了幾個文件。居然有一個hero_list.js文件。這個json文件裏面存放的正是我們苦苦尋找的英雄編號:

英雄編號有了,那麼下一步就是尋找英雄的皮膚編號了。因爲每個英雄的皮膚數量不同,同一個皮膚還可能有炫彩皮膚,通過html文件正則匹配出來不是不行,只是懶~那嘗試一下找找英雄詳情頁有沒有類似與hero_list.js的文件。

這不是剛剛好了麼XD~每個英雄有一個以英雄編號爲前綴的json文件,裏面記錄着有該英雄的皮膚圖片地址。其中的mainImg爲皮膚大圖、iconImg爲皮膚頭像。json文件中還記錄着英雄的其他信息如:定位、技能、描述等等。可以自己嘗試爬取下來,作用。。。。自行開發。

既然每個英雄的json文件中存有皮膚圖片的地址,那就不需要我們自己構建英雄皮膚圖片的地址,而是構建英雄json請求鏈接,從json中解析出來皮膚圖片地址。

代碼實現

需要用到os、requests庫。第一步獲取英雄編號的json文件。文件地址爲:https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js,請求方式爲get。這個地址可以在調試臺中找到。獲取json文件後,然後解析json數據,將英雄編號提取出來。

import os
import requests

#獲取全部英雄json文件
list_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js'
herolist = requests.get(list_url)

#處理json文件
herolist_json = herolist.json()#轉化爲json格式
version = herolist_json['version']#提取版本信息
fileTime = herolist_json['fileTime']#提取json生成時間
heroId = list(map(lambda x:x['heroId'],herolist_json['hero']))#提取英雄Id

拿到英雄編號後,就需要構建出英雄獨立json的地址,通用格式爲:https://game.gtimg.cn/images/lol/act/img/js/hero/【英雄編號】.js。get請求地址獲取英雄獨立json文件,從文件中解析出皮膚地址:

for heroid in heroId:

	herojs_url = "https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js".format(heroid)
	herojs = requests.get(herojs_url).json()#獲取並轉換爲json文件
	heroname = herojs['hero']['name'] + herojs['hero']['title']#提取英雄稱號與別稱
	try:
		os.mkdir(heroname)#創建英雄文件夾
		print("\n\n[+] 文件夾【{}】創建成功,開始下載皮膚".format(heroname))
	except FileExistsError:
		print("\n\n[!] 文件夾【{}】已存在,開始下載皮膚".format(heroname))

	for skin in herojs['skins']:
		skinname = skin['name']#提取皮膚名稱
		print("[-] 正在下載【{}】".format(skinname))
		skinurl = skin['mainImg']#提取皮膚鏈接
		#炫彩皮膚錯誤處理
		try:
			skin_jpg = requests.get(skinurl)
			if skin_jpg.status_code == 200:
				f = open(heroname+"\\"+skinname+".jpg","wb")
				f.write(skin_jpg.content)
				f.close()
		except:
			print("[!] 【{}】爲炫彩皮膚無圖片".format(skinname))

當中有兩個錯誤處理,一個是創建每個英雄獨立文件夾;另外一個是處理炫彩皮膚。因爲炫彩皮膚沒有獨立做的大圖,所以json中並沒有皮膚大圖鏈接。

結尾

去除註釋空行,近30行的代碼即可將英雄聯盟全英雄全皮膚圖片爬取下來。先來看看成品吧~

完整代碼

寫代碼的時候,文件夾創建用的是相對路徑,創建在程序運行的目錄下,所以請在源碼所在目錄下啓動cmd(powershell)運行,否則文件夾創建位置不可預期。

#encoding:utf-8

import os
import requests

#獲取全部英雄json文件
list_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js'
herolist = requests.get(list_url)

#處理json文件
herolist_json = herolist.json()#轉化爲json格式
version = herolist_json['version']#提取版本信息
fileTime = herolist_json['fileTime']#提取json生成時間
heroId = list(map(lambda x:x['heroId'],herolist_json['hero']))#提取英雄Id
#提示信息
print("當前版本爲:{}".format(version))
print("英雄列表更新時間爲:{}\n".format(fileTime))
print("準備開始下載皮膚....")

#下載每個英雄的皮膚
for heroid in heroId:

	herojs_url = "https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js".format(heroid)
	herojs = requests.get(herojs_url).json()#獲取並轉換爲json文件
	heroname = herojs['hero']['name'] + herojs['hero']['title']#提取英雄稱號與別稱
	try:
		os.mkdir(heroname)#創建英雄文件夾
		print("\n\n[+] 文件夾【{}】創建成功,開始下載皮膚".format(heroname))
	except FileExistsError:
		print("\n\n[!] 文件夾【{}】已存在,開始下載皮膚".format(heroname))

	for skin in herojs['skins']:
		skinname = skin['name']#提取皮膚名稱
		print("[-] 正在下載【{}】".format(skinname))
		skinurl = skin['mainImg']#提取皮膚鏈接
		#炫彩皮膚錯誤處理
		try:
			skin_jpg = requests.get(skinurl)
			if skin_jpg.status_code == 200:
				f = open(heroname+"\\"+skinname+".jpg","wb")
				f.write(skin_jpg.content)
				f.close()
		except:
			print("[!] 【{}】爲炫彩皮膚無圖片".format(skinname))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章