爬虫 -- 王者荣耀爬虫,爬取每个英雄的皮肤图片

本文介绍了一种抓取王者荣耀游戏中英雄皮肤图片的方法。通过对皮肤图片URL的分析,找到了英雄ID与皮肤编号之间的规律,并实现了自动化抓取。代码使用Python实现,包括获取英雄ID、下载皮肤图片等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

  • 抓取的重点是找到每个英雄对应的id编号


分析

  • 先观察单个英雄的单张皮肤图片的url(如下图马超的两张皮肤图片所示)
    在这里插入图片描述
    在这里插入图片描述

  • 马超一共有三个皮肤(经典算第一张), 每张皮肤的url分别是
    第一张:
    https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/518/518-bigskin-1.jpg
    第二张:
    https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/518/518-bigskin-2.jpg
    第三张:
    https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/518/518-bigskin-3.jpg

  • 从三个url中不难发现,url只有后面的数字不同(1.jpg、2.jpg、3.jpg)

  • 最大为3,因为这里用的例子是马超(他只有三个皮肤3对应的是最新的皮肤,以此类推)

  • 假设一个英雄皮肤图片有n张,那么此皮肤图片的url结尾则是 1至n .jpg

  • n就是皮肤编号



  • 下面再来看看其他英雄(这次我们找的是猴子

  • 猴子一共有7个图片
    在这里插入图片描述

  • 看一下大圣娶亲的url,结尾是7.jpg
    在这里插安抚安抚入图片描述

  • 与之前的马超规律一样

  • 但有一点不同(都以第一张图片为例,看我加粗的518跟167)

  • 马超的第一张url
    https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/518/518-bigskin-1.jpg

  • 猴子的第一张url
    https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/167/167-bigskin-1.jpg

  • 马超对应的是 518

  • 猴子对应的是 167

  • 通过以上分析可以推断出每个英雄都有对应的id编号id编号皮肤编号结合就可以构成单张的皮肤图片url



接下来找英雄对应的id编号

代码

import requests
import re
import json
import os
import time

# 获取当前时间戳,用于计算爬虫爬取完毕消耗了多少时间
now = lambda: time.time()

# 请求头
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36",
    "Cookie": "pgv_pvid=120529985; pgv_pvi=8147644416; RK=iSx1Z7fSHW; ptcz=d094d0d03f513f6762a4c18a13ddae168782ec153f43b16b604723b27069d0a7; luin=o0894028891; lskey=000100008bc32936da345e2a5268733bf022b5be1613bd2600c10ad315c7559ff138e170f30e0dcd6a325a38; tvfe_boss_uuid=8f47030b9d8237f7; o_cookie=894028891; LW_sid=s116T01788a5f6T2U8I0j4F1K8; LW_uid=Z1q620M7a8E5G6b2m8p0R4U280; eas_sid=m1j6R057x88566P2Z8k074T2N7; eas_entry=https%3A%2F%2Fcn.bing.com%2F; pgv_si=s8425377792; PTTuserFirstTime=1607817600000; isHostDate=18609; isOsSysDate=18609; PTTosSysFirstTime=1607817600000; isOsDate=18609; PTTosFirstTime=1607817600000; pgv_info=ssid=s5339727114; ts_refer=cn.bing.com/; ts_uid=120529985; weekloop=0-0-0-51; ieg_ingame_userid=Qh3nEjEJwxHvg8utb4rT2AJKkM0fsWng; pvpqqcomrouteLine=index_herolist_herolist_herodetail_herodetail_herodetail_herodetail; ts_last=pvp.qq.com/web201605/herolist.shtml; PTTDate=1607856398243",
    "referer": "https://pvp.qq.com/"
}

# 解析函数,返回文本或者二进制或者None
def parse_url(url, get_b=False):
    try:
        response = requests.get(url, headers=headers)
        response.encoding = "gbk"
        assert response.status_code == 200
        if get_b == True:
            return response.content
        else:
            return response.text
    except:
        print("status_code != 200(from parse_url)")
        return None

# 处理单个英雄
def parse_hero_detail(id, name):
    # 保存所有皮肤图片的本地路径
    path = f"./英雄皮肤/{name}"
    if not os.path.exists(path):
        os.makedirs(path, exist_ok=True)

    # 因为不确定每个英雄有多少个皮肤,所以假设单个英雄一共请求10张皮肤,这样就不会出现皮肤缺少的情况
    for num in range(1, 11):
        # 单个英雄皮肤图片的url链接
        api_url = f"https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/{id}/{id}-bigskin-{num}.jpg"

        # 如果返回None,则说明状态码不是200,即没有这个请求的皮肤
        b_data = parse_url(api_url, get_b=True)

        if b_data == None:
            print(f"{name} 一共有{num - 1}个皮肤")
            print("--------------------------------------------------")
            # 没有新的皮肤了,立即退出循环
            break

        img_path = f"{path}/demo{num}.jpg"
        if not os.path.exists(img_path):
            try:
                download_img(img_path, b_data)
            except:
                return
            print(f"{name}{num}张皮肤图片 下载完毕")

# 下载图片
def download_img(path, b_data):
    with open(path, "wb") as f:
        f.write(b_data)


def main():
    # 含有每个英雄对应的id、英雄名称的url
    api_url = "https://game.gtimg.cn/images/yxzj/web201706/js/heroid.js"
    text = parse_url(api_url)

    search_result = re.search('var module_exports = ({.*?})', text, re.S)
    hero_info_str = search_result.group(1)
    hero_info_str = re.sub("'", '"', hero_info_str)
    # 包含 所有英雄以及各自对应的id 的字典
    hero_info_dict = json.loads(hero_info_str)

    for hero in hero_info_dict:
        name, id = hero_info_dict[hero], hero
        print(name, id)
        parse_hero_detail(id, name)


if __name__ == '__main__':
    start = now()                       # 记录起始时间
    main()                              # 主函数
    print(f"耗时: {now() - start}")     # 计算爬虫执行完毕消耗的时间



运行演示

在这里插入图片描述

爬虫运行完毕结果展示(部分)

在这里插入图片描述

补充

  • 艾琳是空的,你们懂的
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值