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

距離上次寫爬蟲文章已通過了許久了,以前寫過一篇20行Python代碼爬取王者榮耀全英雄皮膚 [1],反響強烈,其中有不少同窗但願我再寫一篇針對英雄聯盟官網的皮膚爬取,但苦於事情繁多,便一拖再拖,一直拖到了如今,那麼本篇文章咱們就一塊兒來學習一下如何爬取英雄聯盟全英雄皮膚。html

爬取代碼很是簡單,從上到下可能只須要寫30行左右就能完成,但重要的是分析過程,在此以前,咱們先來了解一下本篇文章須要用到的模塊。python

requests模塊介紹

首先是requests模塊,這是一個模擬瀏覽器請求的模塊,咱們能夠經過它來獲取網頁上的信息,好比百度:git

import requests
url = 'http://www.baidu.com'response = requests.get(url)print(response.text)

運行結果:經過get函數就可以向指定參數的url發送請求,獲得的response對象中封裝了不少響應的信息,其中的text即爲響應內容,注意到獲取的內容裏有亂碼,這是編解碼不一致形成的,只需先獲取二進制數據,而後從新解碼便可:github

import requests
url = 'http://www.baidu.com'response = requests.get(url)print(response.content.decode())

運行結果:json

json模塊

json模塊能夠對json字符串和Python數據類型進行相互轉換,好比將json轉換爲Python對象:瀏覽器

import json
json_str = '{"name":"zhangsan","age":"20"}'rs = json.loads(json_str)print(type(rs))print(rs)

使用loads函數便可將json字符串轉爲字典類型,運行結果:服務器

<class 'dict'>{'name': 'zhangsan', 'age': '20'}

而如果想將Python數據轉爲json字符串,也很是簡單:微信

import json
str_dict = {'name': 'zhangsan', 'age': '20'}json_str = json.dumps(str_dict)print(type(json_str))print(json_str)

經過dumps函數便可將Python數據轉爲json字符串,運行結果:網絡

<class 'str'>{"name": "zhangsan", "age": "20"}

準備工做

前面介紹了兩個模塊,經過這兩個模塊咱們就可以完成這個程序了。在正式開始編寫代碼以前,咱們首先須要分析數據來源,來到官網:https://lol.qq.com/main.shtml,往下拉找到英雄列表:咱們隨意點擊一個英雄進去查看:在皮膚圖片上右鍵點擊檢查:這樣就找到了這個皮膚的url,咱們再選擇第二個皮膚,看看它的url:咱們將安妮全部皮膚的url所有拿出來看看:app

https://game.gtimg.cn/images/lol/act/img/skin/big1000.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1001.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1002.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1003.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1004.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1005.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1006.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1007.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1008.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1009.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1010.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1011.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big1012.jpg

從這些url中能發現什麼規律呢?其實規律很是明顯,url前面的內容都是同樣的,惟一不一樣的是big1000.jpg,而每一個皮膚圖片就是在該url的基礎上加1。

那麼問題來了,它是如何區分這張圖片所屬的英雄的呢?咱們觀察瀏覽器上方的地址:地址上有一個屬性值id爲1,那麼咱們能夠猜想一下,皮膚圖片url中的big1000.jpg是否是由英雄id和皮膚id共同組成的呢?

要想證實咱們的猜測,就必須再去看看其它英雄皮膚是否是也知足這一條件:打開燼的詳情頁面,其id爲202,由此,燼的皮膚圖片url最後部分應爲:big ' + 202 + ' 皮膚編號.jpg,因此其url應爲:

https://game.gtimg.cn/images/lol/act/img/skin/big202000.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big202001.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big202002.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big202003.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big202004.jpghttps://game.gtimg.cn/images/lol/act/img/skin/big202005.jpg

事實是否是如此呢?檢查一下便知:規律已經找到,可是咱們還面臨着諸多問題,好比每一個英雄對應的id是多少呢?每一個英雄又分別有多少個皮膚呢?

查詢英雄id

先來解決第一個問題,每一個英雄對應的id是多少?咱們只能從官網首頁中找找線索,在首頁位置打開網絡調試臺:點擊Network,並選中XHR,XHR是瀏覽器與服務器請求數據所依賴的對象,因此經過它便能篩選出一些服務器的響應數據。此時咱們刷新頁面,在篩選出的內容發現了這麼一個東西:hero_list,英雄列表?這裏面會不會存儲着全部英雄的信息呢?點擊右側的Response,獲得了一串json字符串,咱們將其解析一下:這些數據裏果真存儲的是英雄的信息,包括名字、id、介紹等等,那麼接下來咱們的任務就是將英雄名字和id單獨提取出來,過濾掉其它信息。

忘了告訴大家了,這個文件的url在這裏能夠找到:接下來開始寫代碼:

import jsonimport requests
# 定義一個列表,用於存放英雄名稱和對應的idhero_id = []url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?v=20'response = requests.get(url)text = response.text# 將json字符串轉爲列表hero_list = json.loads(text)['hero']# 遍歷列表for hero in hero_list: # 定義一個字典 hero_dict = {'name': hero['name'], 'id': hero['heroId']} # 將列表加入字典 hero_id.append(hero_dict)
print(hero_id)

首先經過requests模塊請求該url,就可以獲取到一個json字符串,而後使用json模塊將該字符串轉爲Python中的列表,最後循環取出每一個英雄的name和heroid屬性,放入新定義的列表中,這個程序就完成了英雄id的提取。

查詢皮膚個數

接下來解決第二個問題,如何知曉某個英雄究竟有多少個皮膚,按照剛纔的思路,咱們能夠猜想一下,對於皮膚也應該會有一個文件存儲着皮膚信息,在某個英雄的皮膚頁面打開網絡調試臺,並選中XHR,刷新頁面,找找線索:找來找去確實找不到有哪一個文件是跟皮膚有關係的,可是這裏發現了一個31.js文件,而當前英雄的id也爲31,這真的是巧合嗎?咱們將右邊的json字符串解析一下:該json數據中有一個skins屬性,該屬性值即爲當前英雄的皮膚信息,既然找到了數據,那接下來就好辦了,開始寫代碼:

import jsonimport requests
url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/31.js'response = requests.get(url)text = response.text# 將json字符串轉爲列表skins_list = json.loads(text)['skins']skin_num = len(skins_list)

源程序實現

準備工做已經完成了咱們全部的前置任務,接下來就是在此基礎上編寫代碼了:

import requestsimport jsonimport osfrom tqdm import tqdm
try: # 定義一個列表,用於存放英雄名稱和對應的id hero_id = [] skins = [] url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?v=20' response = requests.get(url) text = response.text # 將json字符串轉爲列表 hero_list = json.loads(text)['hero'] # 遍歷列表 for hero in hero_list: # 定義一個字典 hero_dict = {'name': hero['name'], 'id': hero['heroId']} # 將列表加入字典 hero_id.append(hero_dict) # 獲得每一個英雄對應的id後,便可得到英雄對應皮膚的url # 英雄id + 001 # 遍歷列表 for hero in hero_id: # 獲得英雄名字 hero_name = hero['name'] # 獲得英雄id hero_id = hero['id'] # 建立文件夾 os.mkdir('C:/Users/Administrator/Desktop/lol/' + hero_name) # 進入文件夾 os.chdir('C:/Users/Administrator/Desktop/lol/' + hero_name) # 獲得id後便可拼接存儲該英雄信息的url hero_info_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/' + hero_id + '.js' # 經過訪問該url獲取英雄的皮膚數量 text = requests.get(hero_info_url).text info_list = json.loads(text) # 獲得皮膚名稱 skin_info_list = info_list['skins'] skins.clear() for skin in skin_info_list: skins.append(skin['name']) # 得到皮膚數量 skin_info_list = len(info_list) # 得到皮膚數量後,便可拼接皮膚的url,如:安妮的皮膚url爲: # https://game.gtimg.cn/images/lol/act/img/skin/big1000.jpg ~ https://game.gtimg.cn/images/lol/act/img/skin/big1012 s = '' for i in tqdm(range(skins_num), '正在爬取' + hero_name + '的皮膚'): if len(str(i)) == 1: s = '00' + str(i) elif len(str(i)) == 2: s = '0' + str(i) elif len(str(i)) == 3: pass # 拼接皮膚url skin_url = 'https://game.gtimg.cn/images/lol/act/img/skin/big' + hero_id + '' + s + '.jpg' # 訪問當前皮膚url im = requests.get(skin_url) # 保存圖片 if im.status_code == 200: # 判斷圖片名稱中是否帶有'/'、'\' if '/' in skins[i] or '\\' in skins[i]: skins[i] = skins[i].replace('/', '') skins[i] = skins[i].replace('\\', '') with open(skins[i] + '.jpg', 'wb') as f: f.write(im.content)except: print('網絡異常')

運行效果:運行以前記得在桌面上建立一個lol文件夾,若是想改動的話也能夠修改程序:程序中還考慮到了一些其它狀況,好比在爬取這個皮膚的時候會出現問題:由於圖片路徑是以皮膚名字命名的,然而這個皮膚的名字中居然有個/,它是會影響到咱們的圖片保存操做的,因此在保存前將斜槓替換成空字符便可。

還有一個問題就是即便是第一個皮膚,其編號也應該爲000而不是0,因此還須要對其進行一個轉化,讓其始終是三位數。

最後

本篇文章一樣繼承了上篇文章精簡的特色,拋去註釋的話總共30行代碼左右,程序固然還有一些其它地方能夠進一步優化,這就交給你們自由發揮了。

文章代碼已上傳至GitHub:https://github.com/blizzawang/Spider_LOL,有什麼好的建議,歡迎Issues。

References

[1] 20行Python代碼爬取王者榮耀全英雄皮膚 : https://blizzawang.blog.csdn.net/article/details/103190981


本文分享自微信公衆號 - ZackSock(ZackSock)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索