关于如何将HTML打包成EXE可执行文件这件事

PS:时间有点紧张,还没来的及上传视频
关于此事,本人经历良多。
【HTML一键打包EXE工具】
咋说呢,除了文件比较大、价格比较贵之外,没啥缺点,在此不再赘述
【HTML Compiler.exe】
这是个精简版的只有13.5MB
【nwjs】
本篇的主题就是nwjs,它的缺点之一就是更改exe图标比较麻烦,需要手动操作
优点当然是免费
闲话不多说,现在开整!!!
nwjs
我们在这个文件夹里面存放需要打包的html文件,须注意:
将html文件压缩成zip格式,修改扩展名为nw
将nw文件移动到nwjs0.66目录 即 D:\soft\nwjsPack\nwjs0.66
点击该文件夹的地址栏,输入cmd,回车,在命令行界面输入以下内容
copy /b nw.exe+app.nw app.exe到此,文件夹内会出现一个app.exe
打开,就是你自己的index.html界面
文件夹名以文件名命名
login或者index文件放在html文件的根目录
入口文件写死了,必须是 index.html
下载
从
下载 NORMAL版本,我选择的是 v0.66.0 这个版本,也比较过旧的版本,感觉大小差别不是很大,对打包体积的影响甚微。解压缩
这是nwjs的地址:D:\soft\nwjsPack\nwjs0.66
在nwjs的上层目录 nwjsPack创建一个文件夹:html
这样我们就可以创建package.json
在html文件夹内创建package.json并输入一下内容
{
"main": "index.html",
"name": "name",
"description": "admin",
"version": "0.1.0",
"keywords": [
"admin"
],
"window": {
"title": "title",
"icon": "icon.ico",
"toolbar": true,
"frame": true,
"width": 1090,
"height": 750,
"position": "center",
"min_width": 1090,
"min_height": 750,
"resizable": true
},
"webkit": {
"plugin": false,
"java": false,
"page-cache": false
},
"user-agent": "%name %ver %nwver %webkit_ver %osinfo",
"chromium-args": "--allow-file-access-from-files"
}关于json如何更详细的配置,请参考 https://nwjs.org.cn/doc/api/Manifest-Format.html
使用nwjs打开html文件
这一步需要把html文件夹打包成一个单文件,用到的软件是 Enigma Virtual Box
下载第三个就行了
安装好我的地址是 D:\soft\evb
然后把D:\soft\evb 添加到PATH,我们需要用到 enigmavbconsole.exe 这个无界面软件
然后 cmd输入以下内容
enigmavbconsole pack.evb如此就能得到一个可以直接打开真是html的exe文件
这一步需要用到inno setup这个软件,他的功能是将exe打包成一个可以安装的exe
不再赘述
so?我写这个的意义何在?重点当然是以下部分:
为啥?这一步步的太繁琐了,为什么不是点一下,玩一年,诶不是……
所以我用python把这几个步骤黏在了一起,不能辱没 Python的"万能胶水"这一荣誉啊!
创建一个类 名为 GETEXE
重写init
def __init__(self):
self.path = os.getcwd()
self.html_path = os.path.join(self.path, 'html')
self.package_json_path = self.html_path + r'\package.json'
self.icos = os.path.join(self.path, 'ico')
self.nwjs_path = os.path.join(self.path, 'nwjs0.66')
self.nums = 1打包html
def pack_html(self, package, path):
login_page = path + r'\index.html'
ico = self.get_icons()
# 移动ico文件到html
iconame = ico[0]
icopath = ico[1]
copyfile(icopath, path + r'\icon.ico')
# 读取package.json
os.chdir(self.path)
package_json_content = open('package_demo.json')
package_content = json.load(package_json_content)
# package_content['main'] = login_page
package_content['window']['title'] = package
package_content['window']['icon'] = 'icon.ico'
save_json = open(path + r'\package.json', 'w', encoding='utf-8')
save_json.write(json.dumps(package_content, ensure_ascii=False))
save_json.close()压缩,这个是搬来的
def compress_nw(self, source_dir, target_file):
"""zip压缩文件夹
:param source_dir: 需要压缩的文件夹
:param target_file:目标zip文件
:return:"""
with ZipFile(target_file, mode='w') as zf:
# 扫描目录下所有文件
for path, dir_names, filenames in os.walk(source_dir):
path = Path(path)
# 生成在文件夹在压缩包中的相对路径
arc_dir = path.relative_to(source_dir)
for filename in filenames:
zf.write(path.joinpath(filename), arc_dir.joinpath(filename))删除没用的
def remove_files(self, name):
fileList = ['app.exe', 'app.nw', 'replace_app.exe', f'{name}.exe']
for i in fileList:
if os.path.exists(i):
os.remove(i)然后!串连!这是整个的项目代码
# encoding=utf-8
import os
import random
import json
from pathlib import Path
from zipfile import ZipFile
from shutil import copyfile
class GETEXE:
def __init__(self):
self.path = os.getcwd()
self.html_path = os.path.join(self.path, 'html')
self.package_json_path = self.html_path + r'\package.json'
self.icos = os.path.join(self.path, 'ico')
self.nwjs_path = os.path.join(self.path, 'nwjs0.66')
self.nums = 1
def run(self):
# source = self.nwjs_path
# target = os.path.join(self.path, 'nwjs_copy' + str(self.nums))
# # 如果target存在,使用copytree会报错
# copytree(source, target)
# self.nums += 1
# 获取需要打包的总文件夹 list
packages = os.listdir(self.html_path)
for package in packages:
path = os.path.join(self.html_path, package)
self.pack_html(package, path)
self.compress_nw(path, self.nwjs_path + r'\app.zip')
os.chdir(self.nwjs_path)
if os.path.exists('app.nw'):
os.remove('app.nw')
os.rename(r'app.zip', r'app.nw')
os.system('copy /b nw.exe+app.nw replace_app.exe')
os.remove('app.nw')
# 更换到nwjsPack目录,完成html的打包
os.chdir(self.path)
os.system('enigmavbconsole pack.evb')
# 更换到html目录,删除多余文件
os.chdir(self.nwjs_path)
self.remove_files(package)
os.rename('replace_app_boxed.exe', f'{package}.exe')
out_file_path = os.path.join(self.path, 'out_exes')
if os.path.exists(out_file_path + f'\{package}.exe'):
os.remove(out_file_path + f'\{package}.exe')
copyfile(f'{package}.exe', out_file_path + f'\{package}.exe')
os.remove(f'{package}.exe')
# 将生成的exe移动到隔壁文件夹
# break
def remove_files(self, name):
fileList = ['app.exe', 'app.nw', 'replace_app.exe', f'{name}.exe']
for i in fileList:
if os.path.exists(i):
os.remove(i)
# def deal_evb(self, name):
# os.chdir(self.path)
# os.system('enigmavbconsole pack.evb')
# pass
def pack_html(self, package, path):
login_page = path + r'\index.html'
ico = self.get_icons()
# 移动ico文件到html
iconame = ico[0]
icopath = ico[1]
copyfile(icopath, path + r'\icon.ico')
# 读取package.json
os.chdir(self.path)
package_json_content = open('package_demo.json')
package_content = json.load(package_json_content)
# package_content['main'] = login_page
package_content['window']['title'] = package
package_content['window']['icon'] = 'icon.ico'
save_json = open(path + r'\package.json', 'w', encoding='utf-8')
save_json.write(json.dumps(package_content, ensure_ascii=False))
save_json.close()
# 百度搬来的压缩代理,千万别动,我不会改!!!
def compress_nw(self, source_dir, target_file):
"""zip压缩文件夹
:param source_dir: 需要压缩的文件夹
:param target_file:目标zip文件
:return:"""
with ZipFile(target_file, mode='w') as zf:
# 扫描目录下所有文件
for path, dir_names, filenames in os.walk(source_dir):
path = Path(path)
# 生成在文件夹在压缩包中的相对路径
arc_dir = path.relative_to(source_dir)
for filename in filenames:
zf.write(path.joinpath(filename), arc_dir.joinpath(filename))
# 没啥卵用,改了也不能用,先搁着
def get_icons(self):
icos = os.listdir(self.icos)
ico = random.choice(icos)
ico_path = self.icos + '\\' + ico
return [ico, ico_path]
if __name__ == '__main__':
run = GETEXE()
run.run()
"""
复制一份nwjs
创建package.json
压缩html为zip
修改名称为.nw
移动到nwjs
cmd运行copy /b nw.exe+app.nw app.exe
删除app.nw
evb打包
移动打包文件
"""