前言💨
本文的文字及圖片來源於網絡,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯系我們以作處理。
前文內容💨
PS:如有需要 Python學習資料
以及 解答
的小伙伴可以加點擊下方鏈接自行獲取
python免費學習資料以及群交流解答點擊即可加入
基本開發環境💨
- Python 3.6
- Pycharm
相關模塊的使用💨
import os # 內置模塊 用於創建文件
import parsel # 第三方模塊 需要 pip install parsel 安裝 用於解析數據 類似 bs4 但是比 bs4 更好用
import requests # 第三方模塊 需要 pip install requests 安裝 用於請求網頁數據
import re # 內置模塊 正則表達式, 提取數據
安裝Python並添加到環境變量,pip安裝需要的相關模塊即可。
一、💥明確需求
爬取所有王者榮耀英雄的皮膚圖片壁紙
二、網頁數據分析
通過開發者工具中加載的數據,可以查看高清壁紙所對應的url地址。
司空震 這個英雄有兩個皮膚圖片,對於王者榮耀沒玩過的我,一個應該是原皮膚圖片,另一個是購買后皮膚的圖片
https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/537/537-bigskin-1.jpg
https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/537/537-bigskin-2.jpg
這個是兩個圖片的url:
537 :
是每個英雄的ID
bigskin-1 :
這些就是對應的皮膚序列
首先我們要獲取每個英雄的ID
那就要分析英雄資料列表頁的數據內容了。
104個數據,如果玩王者榮耀的話,應該知道這個數剛好對應的是英雄數吧,但是它是亂碼,這個沒有關系,實踐是檢驗真理的唯一標准,請求一下這個url看一下就知道了。
https://pvp.qq.com/web201605/js/herolist.json
請求發現出現的並不是亂碼,並且上面的內容貌似就清晰了,想要的數據就有了啊。
英雄名字、ID、皮膚名字。
但是出現了新的問題
廉頗明明有三個皮膚為什么上面有兩個皮膚名字?如果按照這樣的情況那就爬取不到所有的皮膚圖片了。
既然獲取了英雄的ID值,那試想一下能不能在英雄資料的詳情頁中,找到這些皮膚的名字,或者皮膚的圖片地址呢。
通過開發者工具搜索圖片來源,發現除了本身以外就沒有其他的來源了。
難道后面的序列參數,給一個從1開始的for循環,然后判斷是否能夠請求,如果出現404說明沒有這個圖片地址就跳過?雖然說這樣貌似可以實現,但是會有一個新的問題,那就是每張皮膚圖片,沒有名稱,這樣爬取下來的效果,不知道這張皮膚圖片是什么樣的。
回頭又看了一眼,獲取英雄ID的json數據接口,因為上面有皮膚的名字,當時就再想如果取了json數據里面的皮膚名字,然后通過字符串分割名字,可以得到一個列表,根據len() 計算列表的元素,那樣我就知道,每個英雄的皮膚名字以及序列號了,但是這還需要確定一件事:
按照廉頗為例如果是這樣取值的話,序列為1 的圖片應該是 正義爆表 這個皮膚圖片,所以需要對比一下
從結果上面來說的話,是沒錯的。是這樣按照這樣的思路來爬取圖片,並且還能給每張圖片以皮膚的文字命名。但是還是會少一些皮膚圖片,所以可以在英雄的詳情頁里面查找是否有包含英雄皮膚名字。再按照上述的方式就可以完美解決問題。
有了~搞定 一切思路明了,下面總結一下:
1、請求json數據包,獲取每個英雄的ID
2、拼接每個英雄詳情頁url,請求網頁數據獲取每個皮膚名字
3、根據皮膚名字順序以及英雄ID值,拼接每張圖片url地址
4、保存本地
完整實現代碼
基本上每行代碼都有注釋
import os # 內置模塊 用於創建文件
import parsel # 第三方模塊 需要 pip install parsel 安裝 用於解析數據 類似 bs4 但是比 bs4 更好用
import requests # 第三方模塊 需要 pip install requests 安裝 用於請求網頁數據
import re # 內置模塊 正則表達式, 提取數據
def get_response(html_url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
}
response = requests.get(url=html_url, headers=headers)
# 萬能轉碼方式
response.encoding = response.apparent_encoding
return response
def get_image_url(hero_id):
# 英雄詳情頁URL
# https://pvp.qq.com/web201605/herodetail/106.shtml
# f 字符串格式化,等同於 'https://pvp.qq.com/web201605/herodetail/{}.shtml'.format(hero_id)
hero_url = f'https://pvp.qq.com/web201605/herodetail/{hero_id}.shtml'
# 請求網頁數據
response = get_response(hero_url)
# 轉換成 Selector 對象
selector = parsel.Selector(response.text)
# 提取英雄名字
hero_name = selector.css('.cover-name::text').get()
# 正則表達式 提取所有皮膚名字 split 字符串分割 分割之后返回的是一個列表
skin_name = re.findall('<ul class="pic-pf-list pic-pf-list3" data-imgname="(.*?)">', response.text)[0].split('|')
# len() 計算有多少個元素
num = len(skin_name)
# for 循環 也稱遍歷 左閉右開 int() 轉換成整數類型
for page in range(1, int(num) + 1):
# 皮膚圖片地址
# https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/106/106-bigskin-2.jpg
image_url = f'https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/{hero_id}/{hero_id}-bigskin-{page}.jpg'
# 請求皮膚 圖片地址,圖片是二進制的數據 所以是取 content
image_content = get_response(image_url).content
# 相對路徑 傳入英雄名字 給文件夾命名
path = f'{hero_name}\\'
# 判斷路徑下面是否有這個文件夾,如果沒有就創建文件夾
if not os.path.exists(path):
os.makedirs(path)
# 皮膚圖片保存的路徑 文件夾 + skin_name[int(page) - 1].split('&')[0] 皮膚名字
filename = path + skin_name[int(page) - 1].split('&')[0] + '.jpg'
# filename 路徑 mode 模式 wb 二進制的形式 as 重命名
with open(filename, mode='wb') as f:
# write 寫入保存
f.write(image_content)
print(f'正在保存:{hero_name}', skin_name[int(page) - 1].split('&')[0])
if __name__ == '__main__':
# 英雄數據的接口數據URL
url = 'https://pvp.qq.com/web201605/js/herolist.json'
# 返回數據 為json數據
json_data = get_response(url).json()
# 是一個列表包含 一個一個的字典數據 遍歷獲得 沒一個字典數據
for i in json_data:
# 根據字典取值 提取每個英雄的ID
hero_id = i['ename']
# 調用函數 傳入英雄ID
get_image_url(hero_id)