文章目录
1. 成果展示
2. 单张预览
3. 软件下载
win32
、mac
和linux
用户请自行通过源码打包。
4. 壁纸下载
5. 进度打印
壁纸分辨率及序号如下:
1 > 缩略图
2 > 1024x768
3 > 1280x720
4 > 1280x1024
5 > 1440x900
6 > 1920x1080 (推荐)
7 > 1920x1200
8 > 1920x1440
请选择分辨率 (默认是6):
457/457 |████████████████████| 任务进度: 100% 已用时间: 89S 剩余时间: 0S
请按任意键继续. . .
6. 目标网址
7. 依赖模块
pip install requests
8. 完整代码
# run.py
import re, os, time, json, requests
from urllib.parse import unquote
import concurrent.futures as cf
class WangzheDownloader(object):
# 初始化
def __init__(self):
self.root = './heros/'
if not os.path.exists(self.root):
os.mkdir(self.root)
self.numberSize = 6
self.url = '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={}&iOrder=0&SearchKey=sProdName&iSortNumClose=1&iAMSActivityId=51991&_everyRead=true&iTypeId=2&iFlowId=267733&iActId=2735&iModuleId=2735&_=1607443031450'
res = requests.get(self.url.format(0)).json()
self.totalPage = int(res.get('iTotalPages'))
self.sum = int(res.get('iTotalLines'))
self.count = 0
self.startTime = time.time()
# 选择壁纸分辨率
def size(self):
print('壁纸分辨率及序号如下: ')
size_list = [
'1 > 缩略图',
'2 > 1024x768',
'3 > 1280x720',
'4 > 1280x1024',
'5 > 1440x900',
'6 > 1920x1080 (推荐)',
'7 > 1920x1200',
'8 > 1920x1440'
]
for size in size_list:
print(size)
numberSize = input('请选择分辨率 (默认是6): ')
self.numberSize = numberSize if numberSize else 6
# 获取103位英雄的名字
def name(self):
url = 'https://pvp.qq.com/web201605/js/herolist.json'
res = requests.get(url).json()
self.hero = [item['cname'] for item in res]
# 单张图片下载
def down(self, img_name, img_url):
res = requests.get(img_url)
with open(img_name, 'wb') as f:
f.write(res.content)
self.count += 1
endTime = time.time()
self.show(self.count, self.sum, endTime-self.startTime)
# 爬取每一页
def page(self, numberPage):
res = requests.get(self.url.format(numberPage)).json()
for item in res.get('List'):
# 去除图片名中的特殊字符
img_name = re.sub('[/\:*?"<>|]', '', unquote(item['sProdName']))
# 根据英雄名建立分类文件夹
temp = re.split('[·-]', img_name)
control = True
for each in temp:
if each in self.hero:
control = False
img_dir = self.root+each
if not os.path.exists(img_dir):
os.mkdir(img_dir)
img_name = img_dir+'/'+img_name+'.jpg'
break
if control:
img_dir = self.root+'其它'
if not os.path.exists(img_dir):
os.mkdir(img_dir)
img_name = img_dir+'/'+img_name+'.jpg'
img_url = unquote(item[f'sProdImgNo_{self.numberSize}'])
img_url = img_url.replace('/200', '/0') # /0才是原图,/200都是缩略图
self.down(img_name, img_url)
# 打印进度条
def show(self, num, _sum, runTime):
barLen = 20 # 进度条的长度
perFin = num/_sum
numFin = round(barLen*perFin)
numNon = barLen-numFin
leftTime = (1-perFin)*(runTime/perFin)
print(
f"{num:0>{len(str(_sum))}}/{_sum}",
f"|{'█'*numFin}{' '*numNon}|",
f"任务进度: {perFin*100:.0f}%",
f"已用时间: {runTime:.0f}S",
f"剩余时间: {leftTime:.0f}S",
end='
'
)
if num == _sum:
print()
# 多线程
def main(self):
self.size()
self.name()
with cf.ThreadPoolExecutor() as tp:
for page in range(self.totalPage):
tp.submit(self.page, page)
if __name__ == "__main__":
WangzheDownloader().main()
9. 代码剖析
打开目标网址,通过F12
检查发现,有现有的API
接口可供调用:
API
接口里面存的就是壁纸的下载直链,也提供了图片总张数和总页数的信息:
既然有接口,我们就直接请求接口了,请求url
如下:
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=0&iOrder=0&SearchKey=sProdName&iSortNumClose=1&jsoncallback=jQuery17107126052728750412_1607442410515&iAMSActivityId=51991&_everyRead=true&iTypeId=2&iFlowId=267733&iActId=2735&iModuleId=2735&_=1607443031450
jsoncallback=jQuery17107126052728750412_1607442410515
这个参数不要,不然返回的是带前缀和后缀的jsonp
数据,会影响解析。
API接口返回的json
数据中,List
存的是图片列表,列表长度就是请求参数中的iListNum
的值,默认是20,也就是每页返回20张壁纸。
每张壁纸又有8个url
,从sProdImgNo_1
到sProdImgNo_8
,对应于8种分辨率:
分辨率的对应关系如下:
size_list = [
'1 > 缩略图',
'2 > 1024x768',
'3 > 1280x720',
'4 > 1280x1024',
'5 > 1440x900',
'6 > 1920x1080 (推荐)',
'7 > 1920x1200',
'8 > 1920x1440'
]
你可能会问:不是还有一个sThumbURL
吗?其实这个就是sProdImgNo_1
,不信你可以试试。
sProdName
是图片名字,无论是图片名还是链接,都需要进行url
解码,在python
中通过unquote
解码:
from urllib.parse import unquote
解码后,把图片链接在浏览器中打开,你会发现:怎么都是缩略图?这个将图片链接后面的/200
改为/0
就行了。
img_url = img_url.replace('/200', '/0') # /0才是原图,/200都是缩略图
最后要说的就是图片分类问题了,每个英雄都有很多皮肤,所以我们根据英雄名建立文件夹,将同一英雄的不同皮肤都放到同一文件夹。
王者荣耀英雄名也是找了一个API
接口获取的,获取方式如下:
def name(self):
url = 'https://pvp.qq.com/web201605/js/herolist.json'
res = requests.get(url).json()
self.hero = [item['cname'] for item in res]
至于这个获取英雄名的接口,也是通过F12
检查英雄资料找到的:
接口响应信息如下,直接在浏览器中预览会乱码:
把json
文件下载下来查看,是正常的,其中cname
就是英雄名:
10. 打包教程
10.1. 打包前的准备
先安装pipenv
,在pipenv
创建的虚拟环境下打包,这样打包的软件会很小。
pip install pipenv
10.2. 具体打包流程
- 打开
cmd
控制台 cd
到项目路径- 创建虚拟环境:
pipenv install
- 打开虚拟环境:
pipenv shell
- 安装依赖模块:
pip install requests
- 安装打包工具:
pip install pyinstaller
- 执行打包命令:
pyinstaller -F -i favicon.ico run.py
10.3. 需要注意的点
run.py
就是上方的完整代码,favicon.ico
是软件图标,我用的是下面这个:
下载下来是png
格式,你必须转为ico
格式,这里推荐一个在线转换的工具:
png2ico:https://www.easyicon.net/covert/