python視頻教程欄目精煉介紹如何爬取全英雄皮膚。
免費推薦:python視頻教程
距離上次寫爬蟲文章已經過了許久了,之前寫過一篇20行Python代碼爬取王者榮耀全英雄皮膚
,反響強烈,其中有很多同學希望我再寫一篇針對英雄聯盟官網的皮膚爬取,但苦于事情繁多,便一拖再拖,一直拖到了現在,那么本篇文章我們就一起來學習一下如何爬取英雄聯盟全英雄皮膚。
爬取代碼非常簡單,從上到下可能只需要寫30行左右就能完成,但重要的是分析過程,在此之前,我們先來了解一下本篇文章需要用到的模塊。
requests模塊介紹
首先是requests模塊,這是一個模擬瀏覽器請求的模塊,我們可以通過它來獲取網頁上的信息,比如百度:
import requests url = 'http://www.baidu.com'response = requests.get(url)print(response.text)
運行結果:
通過get
函數就能夠向指定參數的url發(fā)送請求,得到的response對象中封裝了很多響應的信息,其中的text
即為響應內容,注意到獲取的內容里有亂碼,這是編解碼不一致造成的,只需先獲取二進制數據,然后重新解碼即可:
import requests url = 'http://www.baidu.com'response = requests.get(url)print(response.content.decode())
運行結果:
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全部拿出來看看:
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/big1003.jpg https://game.gtimg.cn/images/lol/act/img/skin/big1004.jpg https://game.gtimg.cn/images/lol/act/img/skin/big1005.jpg https://game.gtimg.cn/images/lol/act/img/skin/big1006.jpg https://game.gtimg.cn/images/lol/act/img/skin/big1007.jpg https://game.gtimg.cn/images/lol/act/img/skin/big1008.jpg https://game.gtimg.cn/images/lol/act/img/skin/big1009.jpg https://game.gtimg.cn/images/lol/act/img/skin/big1010.jpg https://game.gtimg.cn/images/lol/act/img/skin/big1011.jpg https://game.gtimg.cn/images/lol/act/img/skin/big1012.jpg
從這些url中能發(fā)現什么規(guī)律呢?其實規(guī)律非常明顯,url前面的內容都是一樣的,唯一不同的是big1000.jpg
,而每個皮膚圖片就是在該url的基礎上加1。
那么問題來了,它是如何區(qū)分這張圖片所屬的英雄的呢?我們觀察瀏覽器上方的地址:
地址上有一個屬性值id為1,那么我們可以猜測一下,皮膚圖片url中的big1000.jpg
是不是由英雄id和皮膚id共同組成的呢?
要想證明我們的猜想,就必須再去看看其它英雄皮膚是不是也滿足這一條件:
打開燼的詳情頁面,其id為202,由此,燼的皮膚圖片url最后部分應為:big ' + 202 + ' 皮膚編號.jpg
,所以其url應為:
https://game.gtimg.cn/images/lol/act/img/skin/big202000.jpg https://game.gtimg.cn/images/lol/act/img/skin/big202001.jpg https://game.gtimg.cn/images/lol/act/img/skin/big202002.jpg https://game.gtimg.cn/images/lol/act/img/skin/big202003.jpg https://game.gtimg.cn/images/lol/act/img/skin/big202004.jpg https://game.gtimg.cn/images/lol/act/img/skin/big202005.jpg
事實是不是如此呢?檢查一下便知:
規(guī)律已經找到,但是我們還面臨著諸多問題,比如每個英雄對應的id是多少呢?每個英雄又分別有多少個皮膚呢?
查詢英雄id
先來解決第一個問題,每個英雄對應的id是多少?我們只能從官網首頁中找找線索,在首頁位置打開網絡調試臺:
點擊Network,并選中XHR,XHR是瀏覽器與服務器請求數據所依賴的對象,所以通過它便能篩選出一些服務器的響應數據。
此時我們刷新頁面,在篩選出的內容發(fā)現了這么一個東西: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中的列表,最后循環(huán)取出每個英雄的name和heroid屬性,放入新定義的列表中,這個程序就完成了英雄id的提取。
查詢皮膚個數
接下來解決第二個問題,如何知曉某個英雄究竟有多少個皮膚,按照剛才的思路,我們可以猜測一下,對于皮膚也應該會有一個文件存儲著皮膚信息,在某個英雄的皮膚頁面打開網絡調試臺,并選中XHR,刷新頁面,找找線索:
找來找去確實找不到有哪個文件是跟皮膚有關系的,但是這里發(fā)現了一個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 osimport tracebackfrom tqdm import tqdmdef spider_lol(): # 定義一個列表,用于存放英雄名稱和對應的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'] # 創(chuàng)建文件夾 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']) # 獲得皮膚數量 skins_num = len(skin_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 try: # 拼接皮膚url skin_url = 'https://game.gtimg.cn/images/lol/act/img/skin/big' + hero_id + '' + s + '.jpg' # 訪問當前皮膚url im = requests.get(skin_url) except: # 某些英雄的炫彩皮膚沒有url,所以直接終止當前url的爬取,進入下一個 continue # 保存圖片 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)def main(): try: spider_lol() except Exception as e: # 打印異常信息 print(e)if __name__ == '__main__': main()
運行效果:
運行之前記得在桌面上創(chuàng)建一個lol文件夾,如果想改動的話也可以修改程序:
程序中還考慮到了一些其它情況,比如在爬取這個皮膚的時候會出現問題:
因為圖片路徑是以皮膚名字命名的,然而這個皮膚的名字中竟然有個/
,它是會影響到我們的圖片保存操作的,所以在保存前將斜杠替換成空字符即可。
還有一個問題就是即使是第一個皮膚,其編號也應該為000
而不是0
,所以還需要對其進行一個轉化,讓其始終是三位數。
最后
本篇文章同樣繼承了上篇文章精簡的特點,拋去注釋的話總共30行代碼左右,程序當然還有一些其它地方可以進一步優(yōu)化,這就交給大家自由發(fā)揮了。