用python爬荣耀皮肤图片(爬虫最基础题,python爬虫教程,超详细+完整代码)

前言

今天,我们用python语言来实现爬荣耀所有英雄的皮肤图片,下载并保存到本地,文章后面有完整代码。

一、思路分析

网站分析

在官网上我们可以看到许多的英雄,每一个英雄都对应着一个网页,而每一个网页网址的区别在于数字不同(大家可以去看看),我们要爬的皮肤图片就在里面。当时我猜测,英雄网页网址的构建是不是存在规律可循,经过分析发现没有任何规律可循,那没办法,我们只能从官网上把每一个英雄网址爬下来,然后一个个去请求(小部分爬不到,估计是异步加载),获得皮肤图片。
在这里插入图片描述
在这里插入图片描述
当我们请求英雄网址,爬下来的数据跟在网页中的数据有出入。
在这里插入图片描述
在这里插入图片描述
于是我去尝试抓包,找到了皮肤图片地址,经过分析发现518(每一个英雄网页都有特定的数字)代表特定的标识,1代表第一张皮肤图片,2代表第一张皮肤图片,3代表第一张皮肤图片,以此类推(其他的都是这样的)在这里插入图片描述
那我们只要构建皮肤图片地址,发送请求就能获取到图片了,但是问题又来了,那我们怎们知道皮肤的数量呢?英雄的皮肤有时多有时少,很不统一,其实我们分析可以发现,皮肤名跟皮肤的图片是按顺序一一对应的,如 英雄名1:图片1 英雄名2:图片2 英雄名3:图片3,以此类推,所以我们可以通过英雄名来知道图片的数量,还能给每一张图片取到对应的名字,一举两得。下面讲一讲代码思路
在这里插入图片描述

代码思路

爬取官网每一个英雄对应的网址,然后一个个去请求,获得皮肤图片的数量(不知道皮肤图片的数量就不知道构建几个皮肤图片地址),构建皮肤图片地址后,再去一张张请求皮肤地址,获得皮肤图片,一张张保存图片。到此就完。

二、环境配置

# python+3.8.8
# requests  2.25.1
# parsel   1.6.0

# 安装
# pip install requests==2.25.1
# pip install parsel==1.6.0

# 如果觉得安装太慢,可以用镜像源
# pip install -i https://mirrors.tuna.tsinghua.edu.cn/help/pypi/ requests==2.25.1
# pip install -i https://mirrors.tuna.tsinghua.edu.cn/help/pypi/ parsel==1.6.0

三、完整代码

import requests
import parsel
import os  # 内置库不需要安装
import re  # 内置库不需要安装
import logging  # 内置库不需要安装


# 发送请求
def get_url(url):
    headers = {
    
    
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'accept-language': 'zh-CN,zh;q=0.9',
        'pragma': 'no-cache',
        'referer': 'https://pvp.qq.com/',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'}

    response = requests.get(url=url, headers=headers)
    # 获取网页编码,避免乱码
    response.encoding = response.apparent_encoding
    return response


# 解析数据
def parser_data(html_data, css_rule, css_1, css_2):
    # 传入html数据
    html = parsel.Selector(html_data)

    # 二次提取
    li = html.css(css_rule)

    data_list = []
    for i in li:
        # 获取英雄名(皮肤名)
        name = i.css(css_1).get()
        # 获取网页地址(图片地址)
        url_data = i.css(css_2).get()
        data_list.append([name, url_data])
    # [[],[],[]......]
    return data_list


def first_data(url):
    html_1 = get_url(url).text
    data_list = parser_data(html_1, '.herolist li', 'a::text', 'a::attr(href)')
    u = []
    for k in data_list:
        # 提取网址中的数字,后面构造图片地址用
        num = re.findall(r'\d+', k[1])[0]
        # 构造每一个英雄的网页地址
        url_ju = 'https://pvp.qq.com/web201605/' + k[1]
        # 替换原先的地址
        k[1] = url_ju
        k.append(num)
        u.append(k)
        print(k)
    # 返回形式[[],[],[],[].....]
    return u


def second_data(url_list):
    total = []

    for g in url_list:
        html_2 = get_url(g[1]).text
        # 皮肤名字爬取不到了,返回为None
        data = parser_data(html_2, '.pic-pf-list ', 'li p::text', '::attr(data-imgname)')
        # 将None值删除
        for y in data:
            y.remove(None)
        # 将英雄名和数字插入
        data[0].insert(0, g[0])
        data[0].insert(1, g[2])
        total.append(data)
        print(data)
    # [[],[],[],[]......]
    return total


def save_file(data, dir_name, file_name):
    '''

    :param data: 图片数据
    :param dir_name: 英雄的目录名
    :param file_name: 保存图片的文件名
    :return:
    '''
    if not os.path.exists('荣耀图片'):
        os.mkdir('荣耀图片')

    if not os.path.exists('王者图片\\' + dir_name):
        os.mkdir('荣耀图片\\' + dir_name)

    with open('荣耀图片\\' + dir_name + '\\' + file_name + '.jpg', mode='wb') as f:
        f.write(data)


# 去除特殊字符,返回集合
def del_str(data_str):
    name_list = []
    jpg_name = data_str.split('|')
    for h in jpg_name:
        t = h.replace('&', '')
        for number in range(10):
            t = t.replace(str(number), '')
        name_list.append(t)
    return name_list, len(name_list)


if __name__ == '__main__':
    # 设置输出的格式
    LOG_FORMAT = "时间:%(asctime)s - 日志等级:%(levelname)s - 日志信息:%(message)s"
    # 对logger进行配置——日志等级&输出格式
    logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
	
	# 官网地址!!!
    url = ''
    d = first_data(url)

    total_list = second_data(d)
    logging.info('总共' + str(len(total_list)) + '个英雄')
    logging.info('开始爬取图片')
    a = 1
    # 遍历每一条数据
    for n in total_list:
        # 计数 英雄数
        dir_name = str(a) + '.' + n[0][0]
        logging.info('正在爬取' + dir_name + '皮肤')
        # 特定的英雄id
        num_id = n[0][1]
        # 传入皮肤名 返回一个集合 ([皮肤名],皮肤数)
        name_num = del_str(n[0][-1])
        a += 1
        # 构建图片地址,并爬取,皮肤地址是从1开始
        for j in range(1, name_num[1] + 1):
            logging.info('正在爬取' + name_num[0][j - 1])
            jpg_url = f'https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/{
      
      num_id}/{
      
      num_id}-bigskin-{
      
      j}.jpg'
            # 爬取皮肤图片
            jpg_content = get_url(jpg_url).content
            # 保存图片
            save_file(jpg_content, dir_name, name_num[0][j - 1])
            logging.info('已保存' + name_num[0][j - 1])
    logging.info(str(len(total_list)) + '个英雄' + '爬取完毕!')



四、总结

爬皮肤图片比较基础,适合刚入门练习爬虫。如果皮肤图片爬多了会遭到反爬,部分爬不到了,我记的刚开始是能爬到的,后来爬的次数多了,就爬不到了,大家可以尝试换ip,设置延迟时间,或者用selenium来爬。
如文章有错误,请指正,最后谢谢大家!!!

猜你喜欢

转载自blog.csdn.net/qq_65898266/article/details/124870582