把文本打包成 ZIM 文件既能直接读还能省空间

最近整理本地资料,希望能节省一些硬盘空间。

因为我用的是当初教育优惠叠加分期免息的最丐版的MacBook Air M4,配置也比较低,硬盘空间也很少。

为了给在投的刊物凑版面费(N记子刊的版面费真可怕),趁着内存和固态以及笔记本电脑最近价格上涨,将之前用的微星游戏本(7945HX+64G+4070 8G+ SN850X 4T)以及一些其他的固态硬盘陆续都卖掉了。

于是手上的存储空间就有点紧张了,所以把手里几乎所有成规模的文本,都打包成了 .zim 格式。

相声文本库、公有领域的世界文学名著、几千篇 AAAI 的论文、几万篇 arXiv 论文,都压缩成了一个个 .zim 文件里。

这篇文章就说说 ZIM 这个格式。

ZIM 是什么

先说清楚 ZIM ,这是 Kiwix 项目用的文件格式。

Kiwix ( https://kiwix.org/en/about/ ) 是做离线内容的开源项目,你可以在没有网络的时候,用 Kiwix 打开一整个维基百科。

ZIM 就是它背后存数据的容器:一个文件,里面可以装下几十万篇文章,打开 Kiwix 就能直接浏览、搜索、跳转。

我这些年一直尽量用本地的离线模型,也经常用这类离线的内容工具。

可能有同学不太理解:现在上网这么方便,何必非得用离线的?

这其实跟我以前做地球科学的经历有关。那会儿在青藏高原、呼伦贝尔、大兴安岭这些地方跑野外,很多区域根本没有网络覆盖,想查点东西只能靠本地文件一条条翻,特别费劲。

所以我一直盼着,要是能把一些网站做成这种既压缩、又能检索、还方便人来读的工具,那就太省事了。

后来有一些文本文件从TXT变成了MD文档,固然是能够用一些工具去搜索,但始终不那么方便,跟网站阅读还是没法比的。

第一个原因:压缩,真的省空间

文本是压缩空间最显著的东西,没有之一。

这个道理想想就明白:一篇中文文章,里面翻来覆去就是那几千个常用字,"的""了""是""我""一个"这些词反复出现,重复率高得吓人。压缩算法最擅长的就是对付这种重复,所以文本的压缩率往往能到七八成甚至更高。几百兆的纯文本,压完可能就剩几十兆。

拿我自己实际做过的几个文件来说:

  • 相声文本库:234 个段子,一百多万字,压成 .zim 之后只有 4.5 MB
  • 公有领域世界文学名著集:559 部作品(荷马、但丁、莎士比亚、托尔斯泰……从古希腊到 20 世纪),113.9 MB。这个数字包含了大量英文原著和翻译版,要是散成一个个 .txt 或者 .md 文件放着,体积要大不少。

其他类型的文件当然也能压缩,图片、音频都有专门的压缩格式,但它们的压缩空间远不如文本。一张已经压过的 JPEG 图片,你再压也压不出多少;而一段纯文本,压出来的效果是立竿见影的。所以如果你手里有大量文本要归档,压缩这件事的收益是最高的。

第二个原因:ZIM 不是"压缩包",不用解压

这是 ZIM 和 zip 最本质的区别。

zip 是个压缩包,想查看一个 zip 里面的文件,得先解压,解压出来的东西再占一份空间,然后才能用里面的文件。用完了想省空间,又得把解压出来的删掉。一来一回,麻烦,而且解压这件事本身就要临时占用额外的磁盘。

ZIM 不一样。它不是"先压起来、要用再解开",而是"压着也能直接读"。你装一个 Kiwix(或者用 libzim 这样的库),就可以直接打开 .zim 文件翻文章、搜关键词,整个过程不需要把整个文件解压出来。数据在磁盘上就一直是压缩状态,读哪一篇,就解哪一篇,读完还保持压缩。

这一点对我这种"存一大堆、偶尔翻一篇"的场景特别友好。我想查相声《买猴》的原文,不用先把 234 个段子全解压出来,直接打开 ZIM 搜"买猴"就行。

第三个原因:它像一个原始版的知识库

这是我觉得最有意思的一点。

现在大家都在让大模型帮忙实现 RAG、挂载访问知识库、实现高效率的向量检索。一个正经的知识库,要做文本切块、向量化、语义相似度检索,维度高、工程复杂。而 ZIM 提供的是另一种东西——一个最原始形态的知识库

它没有向量,没有语义相似度分析,就是一个"文章集合 + 全文索引"。但它是可编程访问的:用 libzim 这类库,程序可以直接遍历 ZIM 里的每一篇文章,读标题、读正文。这就意味着,你可以让一个智能体工具直接去访问一个 ZIM 文件来查资料

模型通过 libzim 打开 ZIM,把文章一篇篇读出来,然后做分词、做主题模型、做统计分析。整个过程里,ZIM 扮演的角色就是"语料库":数据规规整整地待在一个文件里,模型按需取用。

说白了,它就是个"能装很多文章、能全文检索、能被程序读取"的容器。它没有现代知识库那么高的维度,做不了"这段文字和那段文字语义像不像"这种分析,但作为"把一批文本喂给模型去读"的原始底座,完全够用,而且轻量、省事、一个文件走天下。

顺便说一句:怎么用它

如果只是阅读,装个 Kiwix 客户端(用winget和brew都可以安装),打开 .zim 文件就行。

如果想让程序或 AI 读,用 Python 的话装个 libzim

pip install libzim

然后就可以用代码来访问了:

from libzim.reader import Archive
zim = Archive('相声文本库.zim')

# 遍历整个 ZIM 里的所有条目
for i in range(zim.all_entry_count):
    entry = zim._get_entry_by_id(i)
    print(entry.path, entry.title)
    content = entry.get_item().content  # 文章的正文(bytes)

# 或者按路径直接取某一篇
entry = zim.get_entry_by_path('传统单口相声/打灯谜.html')
text = bytes(entry.get_item().content).decode('utf-8')

这么几行,就能把整个 ZIM 里的内容交给下游处理了。 如果你手里也攒着一堆文本,与其让它们散成一地文件,不如试试装进一个 .zim 里。