# 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')