Python爬虫基础--爬取王者荣耀英雄皮肤图片

文章目录

    • 思路分析
    • 涉及到的知识点
    • Json数据说明
      • `herolist.json`:英雄列表
    • 皮肤图片尺寸分析
    • 程序说明
    • 代码
    • 结果(数据)分析
    • 声明


这里只是简单介绍主要内容,详见github,仓库地址:hero-skin-images,下面是仓库页面截图,点击图片可直接跳转到仓库。
Python爬虫基础--爬取王者荣耀英雄皮肤图片_第1张图片

思路分析

这个项目还是比较简单的,因为很多数据都已经json数据中,我们可以很方便的从中取出我们想要的数据。至于下载皮肤图片的主要难点是拼接图片URL,这里有个小坑就是:每张图片都有5种(或者说至少是5种)尺寸的图片,我之前就只发现了其中一种,当然你可以有选择的进行下载;尺寸详见:皮肤图片尺寸分析。

涉及到的知识点

  • 使用requests库进行网络连接,获取网址数据。

  • 使用json库解析json文件(数据)。

  • 使用os库创建文件夹。

  • 字符串拼接。

Json数据说明

我已经将可能有用的json文件都下载了,并且进行了格式化(转换编码为utf8),放在了./wzry/json数据/文件夹下。或者你可以到下面提到的链接中取下载对应的文件(访问json文件URL会自动下载)。

英雄列表介绍主页:https://pvp.qq.com/web201605/herolist.shtml,有herolist.json

herolist.json:英雄列表

  1. 说明:包含英雄id,英雄名,英雄默认皮肤(伴生皮肤:即不用花钱的),英雄类型,英雄皮肤(特指需要花钱买的皮肤,也有可能会在一些活动中会送。注意skin_name 这个属性不一定有,比如新英雄可能就没有)。
  2. 数据URL : https://pvp.qq.com/web201605/js/herolist.json
  3. 举例(部分内容):
[
   {
        "ename": 522,
        "cname": "曜",
        "title": "星辰之子",
        "new_type": 0,
        "hero_type": 1,
        "skin_name": "归虚梦演"
    },
    {
        "ename": 518,
        "cname": "马超",
        "title": "冷晖之枪",
        "new_type": 1,
        "hero_type": 1,
        "hero_type2": 4
    }
]
  1. 存在问题并已经进行处理,详见:存在问题及解决方案。

皮肤图片尺寸分析

英雄皮肤图片信息只涉及到 herolist.json 数据,目前发现图片有5种尺寸,注意:下面的图片大小只是对应英雄的图片尺寸,猜测不是固定的,而是在一定范围内变化。


下面以英雄马超为例,英雄首页:https://pvp.qq.com/web201605/herodetail/518.shtml

形式一URL–猜测用于手机端显示 猜测用途 图片尺寸
https://game.gtimg.cn/images/yxzj/img201606/heroimg/518/518-smallskin-1.jpg 英雄头像 67*67
https://game.gtimg.cn/images/yxzj/img201606/heroimg/518/518-mobileskin-1.jpg 小屏手机英雄背景 600*410
https://game.gtimg.cn/images/yxzj/img201606/heroimg/518/518-bigskin-1.jpg 大屏手机英雄背景 1200*530
形式二URL–猜测是壁纸 猜测用途 图片尺寸
https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/518/518-mobileskin-1.jpg 手机壁纸 727*1071
https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/518/518-bigskin-1.jpg 电脑壁纸 1920*882

程序说明

  1. 测试环境:Python3.7.1,JetBrains PyCharm Community Edition 2018.2.4 x64。

  2. 依赖:requestsjson,如果没有安装requests,用 pip install requests 进行安装即可(json为内置库)。

  3. 使用说明:主程序为:./wzry/wzry.py,运行该程序会将图片下载在当前目录的五个文件夹内,如./wzry/phone-bigskin-images/;如需下载全部英雄图片,请将程序中的 break语句 注释掉。

代码

# -*-coding:utf-8 -*-
"""
@author: yansheng
@file: wzry.py
@time: 2019/9/14
"""
# 爬取王者荣耀的英雄皮肤图片
import requests
import json
import os


def mkdirs(path):
    """
    辅助函数:创建文件夹
    :param path: 文件夹名
    :return:
    """
    # 去除首末的空格
    path = path.strip()
    # 去除尾部 \ 符号
    path = path.rstrip("\\")
    '''
    windows下文件名中不能含有:\ / : * ? " < > | 英文的这些字符 ,这里使用"'"、"-"进行替换。
    :?| 用-替换
    "<> 用'替换
    '''
    # 对于文件夹,有没有.好像都是同一个文件
    # replace方法默认替换所有匹配项
    path = path.replace(":", "-").replace("?", "-").replace("|", "-")
    path = path.replace("<", "'").replace(">", "'").replace("\"", "'")

    # 判断路径是否存在,存在True,不存在False
    is_exists = os.path.exists(path)
    # 判断结果
    if not is_exists:
        # 如果不存在则创建目录,这里使用创建多重目录的函数
        os.makedirs(path)
        print('文件夹\'' + path + '\'创建成功!')
        return True
    else:
        # 如果目录存在则不创建,并提示目录已存在
        print('文件夹\'' + path + '\'目录已存在!')
        return False


def downloadImages():
    """
    主要的函数:获取王者荣耀图片信息,下载图片
    """
    '''
    1.按照分析,创建对应文件夹
    1.1.https://game.gtimg.cn/images/yxzj/img201606/heroimg/518/518-smallskin-1.jpg
        phone-smallskin-images 头像
        phone-mobileskin-images 小屏手机图片
        phone-bigskin-images 大屏手机图片

    1.2.https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/518/518-mobileskin-1.jpg
       wallpaper-mobileskin-images 手机壁纸
       wallpaper-bigskin-images 电脑壁纸

    1.3. 观察url变化情况
    类型1:
    李白的第二个皮肤:https://game.gtimg.cn/images/yxzj/img201606/heroimg/131/131-bigskin-2.jpg
    孙悟空的第二个皮肤:https://game.gtimg.cn/images/yxzj/img201606/heroimg/167/167-bigskin-2.jpg
    
    类型2:
    https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/518/518-mobileskin-1.jpg
    
    不同之处:131/131-bigskin-2
    '''
    # 定义变量
    prefix_url1 = 'https://game.gtimg.cn/images/yxzj/img201606/heroimg/'
    prefix_url2 = 'https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/'
    suffix_url = '.jpg'
    smallskin = '-smallskin-'
    mobileskin = '-mobileskin-'
    bigskin = '-bigskin-'

    phone_smallskin_dirpath = 'phone-smallskin-images'
    phone_mobileskin_dirpath = 'phone-mobileskin-images'
    phone_bigskin_dirpath = 'phone-bigskin-images'
    wallpaper_mobileskin_dirpath = 'wallpaper-mobileskin-images'
    wallpaper_bigskin_dirpath = 'wallpaper-bigskin-images'
    # 创建目录
    mkdirs(phone_smallskin_dirpath)
    mkdirs(phone_mobileskin_dirpath)
    mkdirs(phone_bigskin_dirpath)
    mkdirs(wallpaper_mobileskin_dirpath)
    mkdirs(wallpaper_bigskin_dirpath)

    # 2.获取英雄列表的json数据
    json_url = 'https://pvp.qq.com/web201605/js/herolist.json'  # 英雄的列表信息
    r = requests.get(json_url).text  # json数据--字符串
    # print(r)
    result = json.loads(r)  # 把字符串转换成字典,这里是由88个字典组成的list
    print('王者荣耀的英雄个数:%d' % len(result))  # 王者荣耀的英雄个数:88

    # 循环读取json数据,获得英雄对应数据,拼接图片url,下载图片
    for i in result:
        id = i['ename']  # 英雄id
        cname = i['cname']  # 英雄名
        title = i['title']  # 默认皮肤,即第一个皮肤
        # 判断该英雄是否有skin_name属性(新英雄可能会没有),有就取值,没有就直接将列表置为空
        skin_name_lists = []
        if 'skin_name' in i.keys():
            skin_name = i['skin_name']  # 皮肤名
            skin_name_lists = skin_name.split('|')  # 把字符串变成列表,用|做分隔符
            # 记录英雄的title和skin_name的第一个属性不一样的英雄的id
            diff_ids = [109, 113, 176]
            if id in diff_ids:
                skins_lists = [title] + skin_name_lists[1:]
            else:
                skins_lists = [title] + skin_name_lists
        else:
            skins_lists = [title]
        # 将title 和skin_name_lists合并为列表,然后转为集合,自动去重,
        # 同时保证顺序不变,因为需要设置第一个为伴生皮肤
        skins_set_lists = list(set(skins_lists))
        skins_set_lists.sort(key=skins_lists.index)

        # 拼接网址
        for skin in skins_set_lists:
            # 获取下标,作为英雄皮肤数量
            index = skins_set_lists.index(skin) + 1
            # skin_name_lists.index(skin_name_list)为列表的下标
            # https://game.gtimg.cn/images/yxzj/img201606/heroimg/ + 105 + '/ '+ 105 + '-smallskin-' + 1 + '.jpg'
            # 类型1
            mid_url = '%d' % id + '/' + '%d' % id
            phone_smallskin_url = prefix_url1 + mid_url + smallskin + '%d' % index + suffix_url
            phone_mobileskin_url = prefix_url1 + mid_url + mobileskin + '%d' % index + suffix_url
            phone_bigskin_url = prefix_url1 + mid_url + bigskin + '%d' % index + suffix_url
            # 类型2
            wallpaper_mobileskin_url = prefix_url2 + mid_url + mobileskin + '%d' % index + suffix_url
            wallpaper_bigskin_url = prefix_url2 + mid_url + bigskin + '%d' % index + suffix_url

            # 为方便起见,将对于类型的图片的文件夹和图片url组成 一对字典:
            url_dict = {
                phone_smallskin_dirpath: phone_smallskin_url,
                phone_mobileskin_dirpath: phone_mobileskin_url,
                phone_bigskin_dirpath: phone_bigskin_url,
                wallpaper_mobileskin_dirpath: wallpaper_mobileskin_url,
                wallpaper_bigskin_dirpath: wallpaper_bigskin_url,
            }
            # 遍历字典,取出对应键值,键:图片保存的目录,值:图片网址
            for dirpath in url_dict:
                # 定义保存到本地的图片名称,如:廉颇-1-正义爆轰.jpg
                image_path = dirpath + '/%s-%d-%s.jpg' % (cname, index, skin)
                # print("图片文件名:" + image_path)
                # 将判断放到前面,进行优化
                # 判断文件(图片)是否存在,如果存在就不重复下载,不存在就下载
                if os.path.exists(image_path):
                    print(' ' + image_path + '图片已存在!')
                    continue

                # 获取图片的网址,如果返回状态码为200,下载图片
                img_url = url_dict[dirpath]
                if requests.get(img_url).status_code == 200:
                    print('图片地址:' + img_url)
                    img = requests.get(img_url)

                    # 以二进制形式写文件(下载图片)
                    with open(image_path, 'wb') as f:
                        f.write(img.content)  # 写入图片的二进制数据
                        print(' ' + image_path + '下载成功!')

        # 测试时,只下载一个英雄的皮肤图片;如需下载所有英雄的皮肤图片,请注释下面的break
        break


if __name__ == '__main__':
    downloadImages()
    print('\n**王者荣耀全部英雄皮肤图片已下载成功**')

结果(数据)分析

注:因为该程序是解析json文件获得对应英雄的信息,但是仔细观察后,发现该数据稍有滞后,有部分数据还未进行更新;故该数据非最新数据,仅供参考。(如需要获得最新数据就需要爬取网页元素进行分析,有兴趣者可自行扩展)

1.该文件夹包含了王者荣耀所有英雄的皮肤图片,有5种尺寸。

2.数据汇总(截止:2019年9月14日19:39:23)
英雄数量:95个
皮肤数量:338个(含伴生皮肤)

3.图片尺寸说明(图片尺寸和大小应该是在一定范围内变化,不是定值,以下数据仅供参考):

文件夹 每张图片尺寸(像素) 图片大小(KB) 说明(猜测)
phone-smallskin-images/ 67*67 20 英雄头像
phone-mobileskin-images/ 600*410 200 小屏手机英雄背景
phone-bigskin-images/ 1200*530 450 大屏手机英雄背景
wallpaper-mobileskin-images/ 727*1071 530 手机壁纸
wallpaper-bigskin-images/ 1920*882 900 电脑壁纸

4.文件夹大小

文件夹 文件夹大小(MB)
phone-smallskin-images/ 2
phone-mobileskin-images/ 34.6
phone-bigskin-images/ 68
wallpaper-mobileskin-images/ 61
wallpaper-bigskin-images/ 105

我已将图片全部都下载了,并上传到百度云,有需要可自取。

百度云链接:

链接:https://pan.baidu.com/s/1uFGfSPuKBzYJjEjn6YCx-A
提取码:fd3t
或者扫描下面的二维码
Python爬虫基础--爬取王者荣耀英雄皮肤图片_第2张图片


声明

本项目仅用于学习交流使用,禁止进行商业目的的开发、发布、运营等。数据所有权归 腾讯公司 所有。

你可能感兴趣的:(Python爬虫,Python基础,GitHub)