我做了一个不联网的"个人图书馆",小说漫画随便看
市面上的阅读软件,用着用着就让人烦:要么逼你注册登录,要么悄悄把你的阅读记录传上去,再不然就是开屏广告、弹窗推送。我就想有个简单点的东西------自己攒的小说、漫画、随手存的各种文档,都能在一个地方安安静静地看,断网也能用,数据别出我的电脑。
想清楚之后,干脆自己写一个。最后做出来的,是一个 Windows 下双击就能跑的 .exe,完全离线,不依赖任何账号和服务器。这篇文章把从想法到成品的整个过程记下来,包括中间真踩过的坑,代码都能直接拿去用。
我到底想要个什么
需求其实很朴素,列出来就四条:
- 断网也能看,数据不出本机;
- 小说、漫画、各种文档,各归各的位置,分类我自己说了算;
- 漫画得顺手,竖着滚和左右翻两种都得有;
- 最后是一个
exe,别人(或者说以后的我)双击就跑,不用装 Python、不用装运行时。
就这么点要求。下面说说我是怎么一步步把它做出来的。
先想清楚:它长什么样
我不想搞复杂的数据库。想了个最偷懒也最省事的办法------把文件夹直接当成分类。
你在电脑里建一个"图书馆"文件夹,里面按模块放东西,程序一启动就把这个结构扫出来当书架用:
打开某本书的时候,程序看它"在哪个模块 + 是什么后缀",自动分到对应的阅读器:文本走文本阅读器,图片/漫画走图片阅读器,其它奇奇怪怪的格式就交给系统默认程序打开。
这个设计最大的好处是:你加书、分类、整理,全在资源管理器里拖拖拽拽就行,不用进软件里配半天。
用什么做:选 PySide6,不选 tkinter
界面框架我最后选了 PySide6(Qt 那一套) 。原因很实际:漫画要滚屏、要缩放、要左右翻,Qt 这些东西都是现成的,做起来省心;换成 Python 自带的 tkinter,控件太素,漫画那两种模式得自己造一堆轮子,不划算。Web / Electron 也考虑过,但打包体积大、离线麻烦,大图滚动也不够跟手,pass。
打包用 PyInstaller ,一条命令把 Python 和 Qt 全部塞进一个 exe 里,目标机器啥都不用装。配置和阅读进度就存成同目录下的 config.json 和 progress.json,零依赖。
做的时候我给自己定了一条死规矩:全程不 import 任何网络相关的模块,也不发起任何请求。这样断网一定能用,心里也踏实。
核心就三块:扫库、读文字、看漫画
1. 扫库(文件夹即分类)
启动时把上面的目录结构读出来就行,代码不长:
这里有个小细节:文件名排序不能按字符串排,否则 page2、page10、page9 会乱序(字符串里 10 排在 2 前面)。得用"自然排序",把数字当数字比:
有了这个,page2 就乖乖排在 page10 前面了。
2. 读中文 txt 别乱码
这坑几乎所有做本地阅读器的人都会踩。Windows 上很多小说是 GBK / GB18030 编码的,你上来一个 utf-8 读,满屏方块和问号。我的办法是挨个编码试一遍,谁先成功用谁:
utf-8 打头,失败就退到 gb18030、gbk,最后 latin-1 兜底(这个编码啥都能读,顶多个别字不对,但绝不会崩)。
3. 漫画双模式 + 懒加载(最有意思的部分)
漫画的阅读体验是这整个东西的难点。竖条模式就是纵向滚屏,左右滑动模式就是横向一本本翻。但不管哪种,都不能一把把所有图都加载进来------几百页、每页几 MB,内存直接炸。
所以我抽象了一层"图片来源":不管是"一个文件夹里一堆图",还是打包好的 .cbz / .zip,对外都只暴露"有几张 + 给我第 i 张"。后面阅读器只管按索引取,不关心它从哪来:
然后关键的一招是懒加载:只把当前视口附近的一两张图留在内存里,滚走的页面立刻把像素清掉释放掉。这样哪怕漫画有上千页,内存占用也稳得很:
键盘我也顺手配了:←/→ 翻页,M 切换竖条 / 左右滑动,Esc 关掉。
文本阅读器那边还做了个进度记忆------关掉之前光标停在哪一字,下次打开自动回到那。进度按文件绝对路径当钥匙,存进 progress.json,换台机器只要带着这个文件就还在。
打包成 exe:最有成就感的一步
代码写完,最后一条命令把它变成 exe:
--windowed 是不让运行时弹个黑框,--onefile 是产出单个文件。打完后 config.json / progress.json 放 exe 旁边,复制到哪台电脑都能用。
有个坑得提前说:打包前后"我自己在哪"这个位置会变。开发时我用 __file__ 找资源,打包后程序其实是跑在一个临时目录里的,原来的路径全失效。所以得这么区分:
配置、进度、读取库目录,全都基于这个 BASE,就稳了。
开发里真踩过的几个坑
说几个印象深的,免得你重蹈覆辙。
中文 txt 打开一堆乱码。 上面讲过了,Windows 上小说多半是 GBK 系编码,别硬用 utf-8。按 utf-8 → gb18030 → gbk → latin-1 顺序试探最稳。
漫画几百页,内存直接爆。 一开始图省事全部加载,几十 MB 一张、几百张就崩。改成视口懒加载 + 滚动离开就释放,只留可视区附近一两页的像素,顺滑还省内存。
切换竖条 / 左右滑动后布局乱套。 切换时没把旧布局清干净,新加的图叠在旧的上面,滚动条还打架。后来在切换函数里先把旧布局里所有控件 deleteLater() 再删掉 layout,按新模式重建,并显式把另一个方向的滚动条关掉。
PyInstaller 打包后路径全错。 就是上面那个 __file__ 的坑,用 sys.frozen 判断、资源一律走 exe 同目录的绝对路径就解决了。
图片缩放卡顿。 原图可能是 4000×6000,直接显示很卡。先在内存里 scaled 到显示分辨率再显示,加个抗锯齿,布局计算也基于缩放后的尺寸,就不卡了。
装包时 pip 找不到 PySide6。 有次默认的某个镜像源返回了空列表,死活装不上。后来显式指定官方源 pip install --index-url https://pypi.org/simple ... 就好了;另外注意 Python 版本别太新,太新的版本有时还没对应的预编译包。
无界面环境跑 GUI 测试会报错。 Qt 需要真实显示环境。后来我把界面和逻辑拆开,扫描、排序、读文本、构造图片来源这些纯逻辑用普通函数单独测,GUI 只在自己电脑桌面上验证。
以后还想加什么
现在这个版本够我日常用了,但脑子里还攒了几个想做的:
- EPUB :本质就是 zip 套一堆 xhtml,用标准库
zipfile+ 正则抠正文就行,不用额外依赖;
- PDF :接个
PyMuPDF把每页渲成图,直接复用现在的图片阅读器;
- 目录跳转、书签、笔记:文本按标题正则切章节;
- 再往后就是全文搜索、阅读统计、夜间模式增强这些锦上添花的东西。
最后说两句
回头看,其实就是几十行核心逻辑,加上 PyInstaller 一条命令,就拥有了一个完全离线、数据私有的个人图书馆。真要说最关键的三个工程点,那就是:中文编码兜底、漫画图片懒加载、打包路径别写错。剩下的都是添头。
如果你也想做一个,照着上面的思路和代码拼一拼,一个下午就能跑起来。自己攒的书,自己看得踏实。