本帖最后由 爱飞的猫 于 2024-2-29 07:44 编辑
从 Python 3.2 开始,可以直接让它建立目录而无需事先检查是否已经存在:
os.makedirs('image_path', exist_ok=True)
另外,看了下英雄介绍的 html 页面,其中背景图片地址是可以根据 id 来拼接的:
burl = "//game.gtimg.cn/images/yxzj/img201606/skin/hero-info/" + ename + '/' + ename // 背景图的前缀
function wrap(a, b) {
for (var i = a; i < b; i++) {
var bskin = burl + "-bigskin-" + (i + 1) + ".jpg"; // 拼接
// 无关内容省略
};
}
wrap(0, skins.length);
不用爬页面获取地址,又能省几行。
不过重要的并不是多少行,也要考虑代码的可读性 - 使用各种单字符的变量名可能现在还记得,过一段时间再看可能就不记得了。
最后全部整理一下:
#!/usr/bin/env python3
import os, re, requests, lxml.html
# 根据英雄 ID (ename) 和皮肤索引 (从 1 开始) 来获取对应的皮肤背景图片地址
def get_hero_skin_url(ename, index):
return f'https://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/{ename}/{ename}-bigskin-{index}.jpg'
# 下载英雄皮肤数据到 `./picture/英雄名称` 目录下
def download_skin(hero, name_suffix=''):
# 初始化一些变量
hero_url = f"https://pvp.qq.com/web201605/herodetail/{hero['id_name']}.shtml"
ename = hero['ename']
cname = hero['cname']
# 确保图片下载目录存在
os.makedirs(f'picture/{cname}', exist_ok=True)
# 解析页面信息
doc = lxml.html.fromstring(requests.get(hero_url).content)
# 解析皮肤名称
skin_names = doc.find_class('pic-pf-list')[0].get('data-imgname')
skin_names = re.sub(r'&\d*', '', skin_names)
skin_names = skin_names.split("|")
# 依次下载皮肤图片
for (i, skin_name) in enumerate(skin_names, start=1):
print(f'\33[2K正在下载: {cname}{name_suffix} -- {skin_name} ({i}/{len(skin_names)})\r', end='')
resp = requests.get(get_hero_skin_url(ename, i))
resp.raise_for_status() # 若是请求失败,抛出错误
with open(f'picture/{cname}/{i:02d}-{skin_name}.jpg', 'wb') as f:
f.write(resp.content)
print(f'\33[2K下载完成: {cname}{name_suffix}')
# 地址可选,默认为英雄列表 JSON 数据。
def main(url = 'https://pvp.qq.com/web201605/js/herolist.json'):
hero_data = requests.get(url).json()
for (i, hero) in enumerate(hero_data, start=1):
download_skin(hero, f' ({i}/{len(hero_data)})')
if __name__ == '__main__':
main()
P.S. 可以尝试加入多线程下载
|