爬虫 | 王者荣耀高清壁纸-单线程

# CY3761 | 2021-11-04 11:45

# 把请求事务等封装成函数 一步步进行
import json
import os
import time
import urllib.parse

import requests

# 创建文件夹
# -------------------------------------------------------------
dirPath = '10.王者荣耀/'
jsonDirPath = dirPath + 'json/'
imgDirPath = dirPath + 'img/'

makeDirItems = [
    jsonDirPath,
    imgDirPath
]

for _ in makeDirItems:
    if not os.path.exists(_):
        print('创建目录: %s' % _)
        os.makedirs(_)
# -------------------------------------------------------------
# 数据链接分析与解析
aUrl = ('https://apps.game.qq.com/cgi-bin/ams/module/ishow/V1.0/query/workList_inc.cgi?activityId=2735&sVerifyCode=ABCD'
        '&sDataType=JSON&iListNum=20&totalpage=0&page=1&iOrder=0&iSortNumClose=1&jsoncallback'
        '=jQuery1710035807958553548014_1635991723290&iAMSActivityId=51991&_everyRead=true&iTypeId=2&iFlowId=267733'
        '&iActId=2735&iModuleId=2735&_=1635992383307')
aSplit = aUrl.split('?')
bUrl, bQuery = aSplit[0], aSplit[1]  # 将链接与请求数据进行拆分

# print(bUrl, bQuery, '?'.join([bUrl, bQuery]), sep='\n')

cQs = urllib.parse.parse_qsl(bQuery)
cQs = {_[0]: _[1] for _ in cQs}
del cQs['jsoncallback']  # 删除请求响应前的字符串

# 改变请求页码  默认 0 才是第一页
page = 0
cQs['page'] = page

# 一共 22页 0~21

# print(cQs)
# dEncode = urllib.parse.urlencode(cQs)
# dUrl = '?'.join([bUrl, dEncode])
# print(dUrl)  # 这才是请求的地址
# -------------------------------------------------------------

headers = {
    'referer': 'https://pvp.qq.com/',
    'user-agent': ('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                   'Chrome/95.0.4638.69 Safari/537.36')
}

encoding = 'utf-8'

# 图片请求也使用这个
def request(_url, _encoding=None):
    print(f'请求数据: {_url}')
    resp = requests.get(_url, headers=headers)
    resp.encoding = _encoding if _encoding else encoding
    
    if _url.endswith(imgRepNew):  # 属于图片
        return resp.content  # 图片返回二进制
    else:
        return resp.text  # 返回字符串文本


# 保存文件
def saveData(_data, saveFilePath):
    # 不存在才进行保存
    if not os.path.exists(saveFilePath):
        # print(type(_data))
        if isinstance(_data, bytes):  # 保存图片
            w = open(saveFilePath, 'wb')
        else:
            w = open(saveFilePath, 'w', encoding=encoding)
        
        w.write(_data)
        w.close()
        print(f'写入数据: {saveFilePath}')


# 读取数据
def getData(saveFilePath):
    # 存在才进行读取
    if os.path.exists(saveFilePath):
        r = open(saveFilePath, 'r', encoding=encoding)
        # 读取 json 数据
        if saveFilePath.endswith('json'):
            _data = json.load(r)
        else:
            _data = r.read()
        r.close()
        print(f'读取数据: {saveFilePath}')
        
        return _data


# -------------------------------------------------------------

# 自动处理请求
def auto_handle_request(requestUrl, saveFilePath='', requestEncoding=None):
    if not os.path.exists(saveFilePath):
        saveData(request(requestUrl, requestEncoding), saveFilePath)
    
    # 图片不需要读取
    if saveFilePath.endswith('jpg'):
        return
    
    return getData(saveFilePath)


# 专门为这个 王者荣耀壁纸设计的自动化
def auto_handle_request_json(_page):
    global cQs
    
    cQs['page'] = _page
    
    dEncode = urllib.parse.urlencode(cQs)
    dUrl = '?'.join([bUrl, dEncode])
    # print(dUrl)  # 这才是请求的地址
    
    jsonFilePath = f'{jsonDirPath}%d.json'
    
    return auto_handle_request(
        dUrl,
        jsonFilePath % _page
    )


# 处理图片链接
def get_image_urls(_datas):
    # 图片数据
    dItems = _datas.get('List')
    # 1 ~ 8
    dImgItems = []
    for k, _ in enumerate(dItems):
        dImgItems.append([])  # 初始化图片列表
        
        # 图片名字 sProdName
        sProdName = _.get('sProdName')
        sProdName = urllib.parse.unquote(sProdName)
        sProdName = sProdName.strip()  # 清除空格
        
        # 图片id iProdId
        _iProdId = _.get('iProdId')
        
        for i in range(1, 8 + 1):
            dImgItem = _.get(f'sProdImgNo_{i}')
            dImgItem = urllib.parse.unquote(dImgItem)
            dImgItem = dImgItem.replace(imgRepOld, imgRepNew)
            
            if dImgItem:
                dImgItems[k].append((sProdName, _iProdId, i, dImgItem))
    
    return dImgItems


# 获取总页数  iTotalPages
data = auto_handle_request_json(0)
totalPages = int(data.get('iTotalPages'))

datas = []

for page in range(totalPages + 1):
    data = auto_handle_request_json(page)
    data = get_image_urls(data)
    
    datas.extend(data)
    
    # time.sleep(1)

# 图片存在会取消写入但路径会进行处理导致数据问题

imgDirPathItems = []
for k1, imgItems in enumerate(datas):
    k1 = str(k1)
    for k2, _ in enumerate(imgItems):  # 但名字可能相同
        fileName = _[0]
        iProdId = _[1].zfill(5)
        i = _[2]
        fileSrc = _[3]
        
        # print(fileName, iProdId, fileSrc)
        
        # 图片路径
        imgItemDirPath = f'{imgDirPath}%s/' % iProdId
        
        if not os.path.exists(imgItemDirPath):
            os.makedirs(imgItemDirPath)
            
        # 创建图片名字文件
        txtItemFilePath = f'{imgItemDirPath}{fileName}.txt'
        
        if not os.path.exists(txtItemFilePath):
            with open(txtItemFilePath, 'w') as w:
                pass
        
        # print(imgItemDirPath)

        imgItemFilePath = f'{imgItemDirPath}%s.jpg' % i

        auto_handle_request(fileSrc, imgItemFilePath)
        
        # 可以直接下载文件
        # 资源链接 保存位置 回调函数
        # 回调函数分 3个参数 已经下载的数据块 数据块的大小 远程文件的大小
        # urllib.request.urlretrieve()
        
        # 直接 requests 处理上面进行比较麻烦
        # https://www.cnblogs.com/xiao987334176/p/12655015.html
        
        imgDirPathItems.append((iProdId, fileName))
        
        # break

with open(f'{imgDirPath}/目录对应名称.txt', 'w', encoding=encoding) as w:
    for _ in imgDirPathItems:
        w.write('|'.join(_) + '\n')

    w.write(f'共{len(imgDirPathItems)}个目录\n')

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CY3761

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值