如何阅读《二十四史》？
如果只是想查阅的话，可以使用我最近搞的一个查阅工具。 在做介绍之前，先展示一下我做出来的二十四史搜索主页。这个网站貌似不支持手机登录。如果能看到登录页面的话，用户名是guest，密码是guestguest。 项目是开源的，github地址是： 我们看一下这个网站界面： 在搜索栏输入任何关键词，都会显示相关史料。我们试一下。 首先搜索”项羽“，我们看到，左边就是含有“项羽”两个字的史料段落，一共有267段。右边是“项羽”两个字在二十四史中出现的次数分布。《史记》里出现最多，占比46.44%。其次是《汉书》，占比29.96%。其他史书也多多少少提到过项羽，比如《晋书》、《南史》和《魏书》。 项羽出现在《史记》和《汉书》并不奇怪，因为两者都记录了项羽生活的年代。可为什么其他的史书也会提到项羽呢？ 为了回答这个问题，我们加两个筛选器，把史记和汉书排除出去。 于是就得到了下面的结果。 第一条是《后汉书》的舆服志，提到了有一种帽子叫做“樊哙冠”。我不太懂史料，但看起来是刘邦手下大将樊哙戴的帽子。在鸿门宴上，樊哙听说项羽想要杀刘邦，于是樊哙把下衣撕下来，裹在盾牌上，用头顶着进入宴席。后来就有了这么一种造型的帽子，叫做“樊哙冠”。原来项羽对东汉的时尚产业也有贡献。 第二条也是《后汉书》，但是是郡国志里的。易阳和襄国这两个地方过去叫做邢国，在秦朝叫做信都，后来被项羽给改了。看来项羽在地名上也留下了自己的痕迹。 第三条是《魏书》，“志第六”写的是北魏时期的地形、行政区划和人口统计。里面提到高昌这个地方有个项羽祠。 就不一个一个说了。如果你是一个研究项羽的历史学家，这些史料让你能够很方便地查到和项羽有关的史料。  我们再试试搜索一下别的东西。 我们都知道洛阳是N朝古都。这个N，有人说是九，有人说是十三。不管是几朝古都，洛阳肯定在史料中出现次数很多吧！ 果然，含有洛阳的段落数有2311段。 写到洛阳最多的竟然是《晋书》，竟然占二十四史的11.99%。看来，洛阳在晋朝的存在感很高。想想也挺合理，八王之乱争夺的焦点就是洛阳，司马ABCD们主要在这儿打仗，史官肯定得好好写写。 《北史》提到洛阳第二多，占二十四史的11.64%。我对北魏的历史非常不熟，看来北魏历史上，洛阳也是新闻最多的地方。  能不能搜一些奇奇怪怪的东西呢？ 前几天看了一个关于世界纹身史的视频，二十四史对纹身有没有记载呢？ 果然没有。 为什么呢？因为古代基本不用“纹”这个字，而是用“文”。《礼记·王制》里面写：“东方曰夷，被发文身，有不火食者矣。” 所以正确的做法是搜索“文身”。果然，提到“文身”的史料有54段。 《五代史》里面有一个人叫做雷满。雷满是武陵人，剃发纹身，很有黑社会大哥的感觉。雷满这个人在唐朝末期天下大乱的时候，带着一群同乡，搞了一个几千人的创业土匪团队。后来他的团队竟然被唐朝中央政府收编，成了一方节度使。从这个人的身世，能看出唐朝末期已经是盗匪猖獗了。这条史料也说明，纹身这种行为在唐朝就有帮派盗匪的色彩。 《南史》里记载了一个“文身国”。这个国家在日本东北七千多里的地方，老百姓身上有动物纹身。文身国没有城市，上到国王下到平民都住差不多的房子。国王的“宫殿”就是房子外面挖一圈沟，然后沟里灌上水银。这个国家物产丰富，人民欢乐。如果有人犯罪，轻者用鞭子抽，重的扔到给狮子老虎吃。如果狮子老虎看这个人看了一晚上都不吃，那就赦免。吕思勉在《两晋南北朝史》里认为，文身国就是千岛群岛（日本称北方四岛）的得抚岛。 最有意思的是《史记》“鲁周公世家”的记载。吴王夫差有一次攻打齐国，经过了鲁国。夫差顺便跟鲁国打个劫，说要牛、羊、猪各一百头。鲁国无奈，派孔子的徒弟子贡去找夫差和宰相伯嚭，让子贡“以礼诎之”。结果吴王夫差这人混不吝，直接怼回来一句：“我纹身，跟我讲什么礼？” 吴王这个态度跟楚王的“我蛮夷也”有异曲同工之妙。春秋时期吴国是今天的江苏和安徽这一带。这个记载，暗示春秋时代长江下游的人民有纹身的风俗。 网站展示就这么多。想必这三个例子也可以说明这个网站的使用方法了。下面我讲讲为什么要做这么一个搜索工具。  我以前读历史的时候，往往会在史料查询上浪费很多时间。二十四史很长，一般人也不会在家备上这么大的一堆。维基文库倒是有二十四史的电子版，甚至有搜索功能，但这个功能只能搜索单独史料，而且界面也不是很好用，没有饼状图分布之类的东西。 那么有没有专门为历史资料查询设计的搜索系统呢？ 我发现社科院有这么一个文章“信息时代的文献阅读和史料检索”，作者是河北师范大学的教授王文涛。 我不是史学专业的学生，所以看这篇论文有些困难，但大概归结了这么几个要点： 我按图索骥地去找了找这些史料查询系统，发现真的不是很好用。有的只支持繁体，有的不公开，有的需要注册登录等待审核，甚至有的网站需要像借书一样“借阅”史料数据库。 或许历史学家们对服务器和数据库技术不太熟悉。正巧，我的日常工作就是服务器和数据库。那么，能不能做一个简单易用的史料查询网站呢？ 如果你问一个软件工程师：“怎样才能实现全文检索呢？” 答案八成是ElasticSearch。ElasticSearch是一个开源项目，虽然一般大家不把它称为一个数据库，但毋庸置疑的是它可以用来很快的存储和检索数据。关于ElasticSearch的更多介绍在此不多说，有兴趣的读者可以去官网直接看说明。 ElasticSearch官方有一个前端界面叫做Kibana，在这个界面上你可以搜索，可以做各种图，甚至还可以做权限管理、机器学习、数据实时分析。Kibana满足了我对历史搜索工具的要求：轻量易用，而且不需要培训，基本上一试就会用了。 看来搜索系统和界面都搞定了，现在就需要往里面放史料了。 首先是要把数据标准化。这是我设计的一个简单的数据模型： 注意每一段话都是这么一个json。史料条目是以段为单位的。 接下来我们的工作就是把史料解析成上面这个格式。这个工作耗费了我大量的时间，因为我早期犯了一些错误。 我一开始的工作方法是： 这个工作方式简直是个灾难。 我先四处寻找史料的电子版。网上的电子版很乱，不同史书格式不统一，编码也不一样，有的不全，有的有错别字，有的甚至还有乱码。 我当时尽量去修改校对，补充完全，统一格式，结果花了几个月的时间，才从《史记》整理到《陈书》。这样太慢了，而且最后史料的质量无法保证。乱码多如牛毛，我的手工修正简直是杯水车薪。 后来我发现了“国学网”，这个网站在“信息时代的文献阅读和史料检索”那篇论文里也有提及，而且作者认为“国学网”的质量不低，可以用来做检索。 我写了一个爬虫脚本，把二十四史给爬了下来，然后整理成json。 接下来该把史料喂到ElasticSearch里了。一条一条喂实在太慢了，所以我用了多线程。但多线程很容易被ElasticSearch限流了，所以需要用一个thread pool。 为了保证没有一段话缺失，我还写了一个integration test。如果本地json文件的段落数和ElasticSearch上搜到的段落数一致，那么史料就被录入完整了。 在我把二十四史尽数注入到ElasticSearch后，该考虑如何Host这个网站了。 我需要一个服务器，最好放在云上。AWS只能免费一年，Google Cloud Platform虽然有个免费版，但内存和存储量实在不够运行ElasticSearch，Heroku的ElasticSearch也不是免费的。国内的阿里云腾讯云没有一个免费。可以说免费的云服务这个问题到今天也没有解决。我暂且只能自己Host。 我自己Host也有问题，就是带宽有限，而且每次搬家这个网站估计都得下线一阵子。最好的办法还是放在云上。如果哪个学校有经费搞云服务的话，我把网站的设置方法都写在GitHub上了，直接一步一步来就行了。 最后就是一个锦上添花的东西了。我发现oss版本的Kibana不支持只读模式，这就意味着任何人都能修改Kibana的页面。这个太危险了。我后来把Kibana升级成了7.4.2，这个版本内置了X-Pack插件，可以进行权限管理。我新建了一个只读权限，如果你用文章开头的那个用户名和密码，就可以进入只读权限了。 另外，7.4.2版本的ElasticSearch和Kibana需要Java的JVM，而且版本不支持7和13。我觉得调环境实在太累了，于是写了个docker-compose文件。如果想用docker安装，直接docker-compose up就行了。 这个网站的来源是国学网，我没有做任何的校对工作。千万不要用我的网站代替史料的阅读，它只是一个搜索工具。 我不想通过这个项目盈利，因为这只是个公益项目。我的想法很简单，就是觉得史料搜索系统很好玩，很值得一做。历史专业者可以用它做学术研究，历史爱好者们可以在上面随便搜索看。你可以看看自己的老家在二十四史里面出现过没有，查查有没有古人和自己重名，搜搜今天的网络流行语在古书里有没有出现过。如果有人用的开心，我就觉得努力就没有白费。 最后，如果有人想帮我Host这个网站，或者提交Pull Request，笔者不胜感激。如果用起来有任何不方便，也欢迎在GitHub上提交issue。 祝大家玩的愉快。