一、为什么想下载wallpaper Engine的壁纸
在游戏平台steam上,有一个壁纸软件wallpaper Engine,人称小红车,里面有各种好看的动态壁纸和视频,可以给我们的电脑设置动态桌面,非常好用。
用过几次后,我有了一些痛点,就是软件只能启动的时候才有这个桌面壁纸(当然这非常合理),但是我很喜欢这张壁纸,希望开机后,或不启动steam和wallpaper Engine的时候,也可以用这个壁纸当桌面。
同时有些视频我很喜欢,但是又不想当壁纸,就想下载下来放到其他文件夹里,所以就产生了这个需求,把wallpaper里面的壁纸和视频下载一下。
二、 这些代码能做到什么
在有了下载的想法以后,我着手研究起来,首先我想下载的是:壁纸和视频,视频文件的话还好说,在本地的文件夹里就有,但是壁纸文件时pkg封装好的,因为很多壁纸里有一些动态效果,这个应该是它的统一格式。
于是我在网上找到了大佬写的解包exe程序
repkg包地址:https://github.com/notscuffed/repkg/releases
根据这个程序,我进行了二次开发,可以批量的解压pkg的图片,然后放入必定文件夹中,加入了一些去重、重命名的功能,以及可以指定白名单不加入下载队列中。
三、代码展示和下载
这里我给出了我的代码仓库地址,github和gitcode,具体使用方法在readme文件中有介绍。
https://gitcode.net/CCGGAAG/Python
https://github.com/CCGGAAG/wallpaper_download
这里要注意的是,直接复制我的代码不能跑,因为缺一个repkg.exe,从我上面给出的仓库地址下载就行了。
# -*- coding:utf-8 -*-
import os
import shutil
import yaml
import hashlib
import randomclass CopyWallpaper:def __init__(self, steam_url, copy_dir):"""类的初始化,两个地址必需传递为本地电脑的绝对路径:param steam_url: wallpaper的数据文件夹,例如:D:/**/Steam/steamapps/workshop/content/431960:param copy_dir: 你要转移存储文件的地址"""self.steam_url = steam_urlself.copy_dir = copy_dirself.file_format = [".mp4", ".MP4", ".MOV", ".mov", ".avi", ".AVI", ".webm", ".WEBM", ".pkg"]self.video_format = [".mp4", ".MP4", ".MOV", ".mov", ".avi", ".AVI", ".webm", ".WEBM", ".mp3"]self.pkg_file_format = [".png", ".PNG", ".jpg", ".JPG", ".jpeg", ".JPEG", ".gif", ".GIF"]if "img" not in os.listdir(self.copy_dir):os.makedirs(self.copy_dir + "/img")def get_repkg_img(self, list_pkg):"""通过本地的pkg文件地址列表,将pkg解压后的图片文件移动到指定文件夹(copy_dir)下:param list_pkg: 本地的pkg文件地址列表:return:"""pkg_path = os.getcwd() + "/repkg"base_driver = pkg_path[0]for i in list_pkg:if "dispose" not in os.listdir(pkg_path):os.makedirs(pkg_path + "/dispose")self.file_copy([i], "./repkg/dispose")print("-----------------------------------------------------------")print("pkg文件%s" % i)pkg_name = i[str(i).rfind("/") + 1:]cmd_line = "%s: && cd %s && RePKG.exe extract -o ./dispose ./dispose/%s" % (base_driver, pkg_path, pkg_name)os.system(cmd_line)img_list = self.get_format_file_list(dir_path=pkg_path + "/dispose/materials", file_format=self.pkg_file_format)[self.file_copy([j], self.copy_dir + "/img") for j in img_list if os.path.getsize(j) >= 100000]shutil.rmtree("./repkg/dispose/")def file_copy(self, file_list, copy_dir=None):"""一个复制文件的方法,把列表中地址的文件拷贝到指定文件夹:param file_list: 一个本地文件地址的列表:param copy_dir: 默认是self.copy_dir:return:"""if copy_dir is None:copy_dir = self.copy_dirfor i in file_list:copy_file_list = os.listdir(copy_dir)file_name = i[str(i).rfind("/") + 1:]if file_name in copy_file_list:new_name = str(i).replace(file_name, ("重复%s" % random.randint(10000, 19999) + file_name))shutil.copy(i, new_name)shutil.move(new_name, copy_dir)print("移动文件:%s" % new_name)else:shutil.copy(i, copy_dir)print("拷贝文件:%s" % i)def get_format_file_list(self, dir_path, file_list=None, file_format=None):"""通过一个目录地址,递归获取目录下所有‘规定格式’的文件的地址(默认文件类型:视频、图片、pkg):param dir_path:文件夹绝对地址:param file_list:默认None:param file_format:默认None:return: file_list"""if file_list is None:file_list = []if file_format is None:file_format = self.file_format + self.pkg_file_formatfile_in_dir_list = os.listdir(dir_path)for file_name in file_in_dir_list:url_join = dir_path + '/' + file_namefile_type = os.path.splitext(url_join)[1]if os.path.isdir(url_join):self.get_format_file_list(url_join, file_list)elif file_type in file_format:file_list.append(url_join)else:passreturn file_listdef split_list(self, file_list):"""处理单个wallpaper地址列表,变为视频和pkg文件地址的两个列表:param file_list::return: mp4_list, pkg_list"""list_mp4 = [x for x in file_list if os.path.splitext(x)[1] in self.video_format]list_pkg = [y for y in file_list if ".pkg" == os.path.splitext(y)[1]]img = [z for z in file_list if os.path.splitext(z)[1] in self.pkg_file_format]list_img = [m for m in img if m.find("preview.jpg") == -1]return list_mp4, list_pkg, list_imgdef start_get_wallpaper_file(self, pkg_only=False, mp4_only=False, new_file_only=False):"""一键获取所有wallpaper文件:param pkg_only: 是否获取pkg图片文件:param mp4_only: 是否获取视频文件:param new_file_only: 是否仅获取新订阅的文件:return:"""whole_file_list = self.get_format_file_list(self.steam_url)if new_file_only:self.init_installed_file_list()with open("./repkg/file_path_list.yaml", 'rb') as f:path_list = yaml.load(f, Loader=yaml.FullLoader)with open("./repkg/md5_list.yaml", 'rb') as f:md5_list = yaml.load(f, Loader=yaml.FullLoader)update_file_list = [i for i in whole_file_list if i not in path_list and self.get_md5(i) not in md5_list]print(update_file_list)else:update_file_list = whole_file_listlist_mp4, list_pkg, list_img = self.split_list(update_file_list)if pkg_only:self.get_repkg_img(list_pkg)[self.file_copy([j], self.copy_dir + "/img") for j in list_img if os.path.getsize(j) >= 100000]if mp4_only:self.file_copy(list_mp4)if not pkg_only and not mp4_only:print("请设置拷贝图片还是视频")@staticmethoddef get_md5(filename):"""获取文件md5值:param filename: 文件路径:return: md5值"""md5_handle = hashlib.md5()md5_file = open(filename, "rb")md5_handle.update(md5_file.read())md5_file.close()md5_value = md5_handle.hexdigest()return md5_valuedef init_installed_file_list(self):"""初始化已经订阅的所有壁纸信息,并保存为文件"""whole_file_list = self.get_format_file_list(self.steam_url)if "file_path_list.yaml" not in os.listdir("./repkg"):print("新建file_path文件")fd = open("./repkg/file_path_list.yaml", mode="w", encoding="utf-8")fd.close()data = whole_file_listfw = open("./repkg/file_path_list.yaml", 'a', encoding='utf-8')yaml.dump(data, fw)fw.close()if "md5_list.yaml" not in os.listdir("./repkg"):print("新建md5文件")fd = open("./repkg/md5_list.yaml", mode="w", encoding="utf-8")fd.close()data = [self.get_md5(i) for i in whole_file_list]fw = open("./repkg/md5_list.yaml", 'a', encoding='utf-8')yaml.dump(data, fw)fw.close()
运行这个程序的代码:
wallpaper_dir = "D:/Program Files (x86)/Steam/steamapps/workshop/content/431960"
output_dir = "D:/test123"
test = CopyWallpaper(wallpaper_dir, output_dir)
# 全部类型拷贝
test.start_get_wallpaper_file(pkg_only=True, mp4_only=True, new_file_only=False)
四、如何使用这个项目
在你下载好项目后,可以看接下来的文章讲解,也可以看项目本身的readme文件,CSDN和那里的内容是一样的。
1.首先进入当前项目的命令行页面,执行pip install -r requirements.txt
或者 pip install PyYAML,因为本项目只使用了这一个第三方库。
2.打开srart.py文件,将两个参数改成你本地的,
- wallpaper_dir:你的本地wallpaper软件文件夹地址
- output_dir:你想拷贝到的文件夹地址
3.使用python运行start.py文件即可
4.如果你想要省劲,修改paper.bat文件中的cmd命令,也就是进入当前项目文件夹,并且运行start.py文件,把这个bat命令做成一个快捷方式,这样只用点击bat命令就可以拷贝文件资源了,非常方便!!!
5.当你多次运行这个文件后,会发现每次都将所有资源下载了,所以在start.py文件中,将test.init_installed_file_list()的注释去掉,然后运行一下即可,会生成一个当前订阅的资源名单,以后再拷贝文件的话,会跳过名单上的资源。
五、项目参数
1.执行获取文件的方法start_get_wallpaper_file():
- pkg_only,默认为True,指定是否解压并拷贝pkg封装的图片文件
- mp4_only,默认为True,指定是否拷贝视频文件
- new_file_only,默认为True,名单中的资源不再下载,只下载名单上没有的
2.将已订阅的壁纸放入不下载名单中init_installed_file_list()
运行这个方法后,会在repkg文件夹中,生成yaml文件,里面是当前已经订阅的壁纸文件地址,下次再运行start_get_wallpaper_file()方法下载文件时,就会忽略这个yaml文件中记录的路径。