一、为什么想下载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 random
class 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_url
self.copy_dir = copy_dir
self.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_dir
for 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_format
file_in_dir_list = os.listdir(dir_path)
for file_name in file_in_dir_list:
url_join = dir_path + '/' + file_name
file_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:
pass
return file_list
def 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_img
def 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_list
list_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("请设置拷贝图片还是视频")
@staticmethod
def 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_value
def 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_list
fw = 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文件中记录的路径。