# CY3761 | 2021-11-04 18:23 import json import os import queue import time import urllib import requests from urllib import parse import threading from queue import Queue # 王者荣耀-官网 https://pvp.qq.com # 王者荣耀-高清壁纸 https://pvp.qq.com/web201605/wallpaper.shtml | 游戏资料-游戏壁纸 # 多线程下载王者荣耀-高清壁纸 使用 queue # 生产者线程 page_queue.get img_url_queue.put # 请求json数据获得图片链接, 并对图片链接进行处理成可下载的图片链接 # 消费者线程 img_url_queue.get # 进行读取图片链接,并进行下载图片 # ------------------------------------------------------------- # 创建文件夹 def makeDirPlus(_dirPath): if not os.path.exists(_dirPath): print('创建目录: %s' % _dirPath) os.makedirs(_dirPath) # ------------------------------------------------------------- # 请求数据 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 get_request(requestUrl, saveFilePath='', requestEncoding=None): if not os.path.exists(saveFilePath): saveData(request(requestUrl, requestEncoding), saveFilePath) # 图片不需要读取 if saveFilePath.endswith('jpg'): return return getData(saveFilePath) # ------------------------------------------------------------- # 获取json数据 def get_json(_page): global cQs cQs['page'] = _page dEncode = urllib.parse.urlencode(cQs) dUrl = '?'.join([bUrl, dEncode]) # print(dUrl) # 这才是请求的地址 jsonFilePath = f'{jsonDirPath}%d.json' return get_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, imgSize + 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 # ------------------------------------------------------------- # 生产者线程 class P(threading.Thread): def __init__(self, j_queue, i_queue): super(P, self).__init__() self.j_queue = j_queue # 页面数 self.i_queue = i_queue # 图片数 # 进行数据请求获取JSON数据, 从JSON数据获取图片链接并处理成可下载的链接 def run(self) -> None: global imgItems # 队列不为空 执行以下代码段 while not self.j_queue.empty(): # 获取取URL并发送请求 / 获取JSON数据 # 获取JSON数据后, 从JSON数据获取图片链接并处理成可下载的链接 # sProdName, _iProdId, i, dImgItem datas = get_image_urls(get_json(self.j_queue.get())) for k1, v1 in enumerate(datas): k1 = str(k1) for k2, v2 in enumerate(v1): fileName = v2[0] iProdId = v2[1].zfill(5) i = v2[2] fileSrc = v2[3] # 图片路径 imgItemDirPath = f'{imgDirPath}%s/' % iProdId makeDirPlus(imgItemDirPath) # 创建图片名字文件 saveData('', f'{imgItemDirPath}{fileName}.txt') self.i_queue.put((fileSrc, f'{imgItemDirPath}%s.jpg' % i)) imgItems.setdefault(iProdId, fileName) pass # for in # 创建文件夹与对应各图片名字文件 | 一页的数据 20个 # 生成图片路径与本地路径数据 并且进行 # 最后需要 这里进行图片名字组装并写入一个文件 pass # ------------------------------------------------------------- # 消费者线程 class C(threading.Thread): def __init__(self, j_queue, i_queue): super(C, self).__init__() self.j_queue = j_queue # 页面数 self.i_queue = i_queue # 图片数 # 获取图片链接并下载图片 def run(self) -> None: while True: try: get = self.i_queue.get(timeout=32) # 获取图片并下载 | 超时结束 get_request(get[0], get[1]) except queue.Empty as e: # 没有数据就停止循环 break pass # ------------------------------------------------------------- # 全局数据 dirPath = '10.王者荣耀/' jsonDirPath = dirPath + 'json/' imgDirPath = dirPath + 'img/' imgRepOld = '/200' imgRepNew = '/0' imgSize = 8 imgItems = {} makeDirItems = [ jsonDirPath, imgDirPath ] 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' # ------------------------------------------------------------- # 数据链接分析与解析 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 | 第一页 # ------------------------------------------------------------- def main(): s = time.time() for _ in makeDirItems: makeDirPlus(_) # 获取总页面 总图片数 data = get_json(0) totalPages = int(data.get('iTotalPages')) totalLines = int(data.get('iTotalLines')) # 设置2个队列 j_queue = Queue(totalPages) # 页面数 i_queue = Queue(totalLines * imgSize) # 图片数 for page in range(0, totalPages): # 传入链接页面 page j_queue.put(page) pass # 创建生产者线程对象 同时进行 ts = [] for _ in range(5): t = P(j_queue, i_queue) # 存入2个队列对象 ts.append(t) t.start() # 创建消费者线程对象 同时进行 for _ in range(10): t = C(j_queue, i_queue) ts.append(t) t.start() for _ in ts: _.join() with open(f'{imgDirPath}目录对应名称.txt', 'w', encoding=encoding) as w: for _ in imgItems: k = _ v = imgItems[_] w.write('|'.join([k, v]) + 'n') w.write(f'共{len(imgItems)}个目录n') e = time.time() print('耗时 %.8f' % (e - s)) # ------------------------------------------------------------- if __name__ == '__main__': main()
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)