關(guān)于如何將HTML打包成EXE可執(zhí)行文件這件事

PS:時(shí)間有點(diǎn)緊張,還沒(méi)來(lái)的及上傳視頻
關(guān)于此事,本人經(jīng)歷良多。
【HTML一鍵打包EXE工具】
咋說(shuō)呢,除了文件比較大、價(jià)格比較貴之外,沒(méi)啥缺點(diǎn),在此不再贅述
【HTML Compiler.exe】
這是個(gè)精簡(jiǎn)版的只有13.5MB
【nwjs】
本篇的主題就是nwjs,它的缺點(diǎn)之一就是更改exe圖標(biāo)比較麻煩,需要手動(dòng)操作
優(yōu)點(diǎn)當(dāng)然是免費(fèi)
閑話不多說(shuō),現(xiàn)在開整?。?!
nwjs
我們?cè)谶@個(gè)文件夾里面存放需要打包的html文件,須注意:
將html文件壓縮成zip格式,修改擴(kuò)展名為nw
將nw文件移動(dòng)到nwjs0.66目錄 即 D:\soft\nwjsPack\nwjs0.66
點(diǎn)擊該文件夾的地址欄,輸入cmd,回車,在命令行界面輸入以下內(nèi)容
copy /b nw.exe+app.nw app.exe到此,文件夾內(nèi)會(huì)出現(xiàn)一個(gè)app.exe
打開,就是你自己的index.html界面
文件夾名以文件名命名
login或者index文件放在html文件的根目錄
入口文件寫死了,必須是 index.html
下載
從
下載 NORMAL版本,我選擇的是 v0.66.0 這個(gè)版本,也比較過(guò)舊的版本,感覺大小差別不是很大,對(duì)打包體積的影響甚微。解壓縮
這是nwjs的地址:D:\soft\nwjsPack\nwjs0.66
在nwjs的上層目錄 nwjsPack創(chuàng)建一個(gè)文件夾:html
這樣我們就可以創(chuàng)建package.json
在html文件夾內(nèi)創(chuàng)建package.json并輸入一下內(nèi)容
{
?"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"
}關(guān)于json如何更詳細(xì)的配置,請(qǐng)參考 https://nwjs.org.cn/doc/api/Manifest-Format.html
使用nwjs打開html文件
這一步需要把html文件夾打包成一個(gè)單文件,用到的軟件是 Enigma Virtual Box
下載第三個(gè)就行了
安裝好我的地址是 D:\soft\evb
然后把D:\soft\evb 添加到PATH,我們需要用到 enigmavbconsole.exe 這個(gè)無(wú)界面軟件
然后 cmd輸入以下內(nèi)容
enigmavbconsole pack.evb如此就能得到一個(gè)可以直接打開真是html的exe文件
這一步需要用到inno setup這個(gè)軟件,他的功能是將exe打包成一個(gè)可以安裝的exe
不再贅述
so?我寫這個(gè)的意義何在?重點(diǎn)當(dāng)然是以下部分:
為啥?這一步步的太繁瑣了,為什么不是點(diǎn)一下,玩一年,誒不是……
所以我用python把這幾個(gè)步驟黏在了一起,不能辱沒(méi) Python的"萬(wàn)能膠水"這一榮譽(yù)??!
創(chuàng)建一個(gè)類 名為 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()
? ?# 移動(dòng)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()壓縮,這個(gè)是搬來(lái)的
def compress_nw(self, source_dir, target_file):
? ?"""zip壓縮文件夾
? ?:param source_dir: 需要壓縮的文件夾
? ?:param target_file:目標(biāo)zip文件
? ?:return:"""
? ?with ZipFile(target_file, mode='w') as zf:
? ? ? ?# 掃描目錄下所有文件
? ? ? ?for path, dir_names, filenames in os.walk(source_dir):
? ? ? ? ? ?path = Path(path)
? ? ? ? ? ?# 生成在文件夾在壓縮包中的相對(duì)路徑
? ? ? ? ? ?arc_dir = path.relative_to(source_dir)
? ? ? ? ? ?for filename in filenames:
? ? ? ? ? ? ? ?zf.write(path.joinpath(filename), arc_dir.joinpath(filename))刪除沒(méi)用的
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)然后!串連!這是整個(gè)的項(xiàng)目代碼
# 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會(huì)報(bào)錯(cuò)
? ? ? ?# 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移動(dòng)到隔壁文件夾
? ? ? ? ? ?# 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()
? ? ? ?# 移動(dòng)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()
? ?# 百度搬來(lái)的壓縮代理,千萬(wàn)別動(dòng),我不會(huì)改?。?!
? ?def compress_nw(self, source_dir, target_file):
? ? ? ?"""zip壓縮文件夾
? ? ? ?:param source_dir: 需要壓縮的文件夾
? ? ? ?:param target_file:目標(biāo)zip文件
? ? ? ?:return:"""
? ? ? ?with ZipFile(target_file, mode='w') as zf:
? ? ? ? ? ?# 掃描目錄下所有文件
? ? ? ? ? ?for path, dir_names, filenames in os.walk(source_dir):
? ? ? ? ? ? ? ?path = Path(path)
? ? ? ? ? ? ? ?# 生成在文件夾在壓縮包中的相對(duì)路徑
? ? ? ? ? ? ? ?arc_dir = path.relative_to(source_dir)
? ? ? ? ? ? ? ?for filename in filenames:
? ? ? ? ? ? ? ? ? ?zf.write(path.joinpath(filename), arc_dir.joinpath(filename))
? ?# 沒(méi)啥卵用,改了也不能用,先擱著
? ?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()
? ?"""
? ?復(fù)制一份nwjs
? ?創(chuàng)建package.json
? ?壓縮html為zip
? ?修改名稱為.nw
? ?移動(dòng)到nwjs
? ?cmd運(yùn)行copy /b nw.exe+app.nw app.exe
? ?刪除app.nw
? ?evb打包
? ?移動(dòng)打包文件
? ?"""