Telegram对于中文的支持并不很好,尤其是搜寻功能遇上汉字即与残废无异。。,原因究竟是什么呢??让我们来逐步抽丝剥茧吧
首先,我们看看Telegram核心td-lib是如何存储消息的。这是MessagesDb.cpp,从12到14行我们可以知道Telegram使用SQLite作为资料库:
#include“ td / db / SqliteConnectionSafe.h”
#include“ td / db / SqliteDb.h”
#include“ td / db / SqliteStatement.h”
接下来,我们可以发现这个数据库中有很多表,但是我们只关心messages_fts 这个虚拟表。那么,这个fts又是什么呢??
如果不存在,则创建虚拟表使用fts5的messages_fts(文本,content ='messages',content_rowid ='search_id',tokenize =“ unicode61 remove_diacritics 0 tokenchars'\ a'”)
原来,fts实际上是全文搜索,也就是所谓的全文搜索,而fts5则是SQLite内建可以提供全文搜索的模组。
说到这里,来先打个岔谈谈字串搜寻。在高中演算法竞赛中,除了朴素的暴力解外,最常见而广为人知的方法有两种:KMP演算法与其他基于散列的演算法。前者是由资讯界史诗级教授Donald E. Knuth及Pratt,莫里斯于1977年提出。
而SQLite fts5比较类似基于hash的演算法,他的做法大约如下:
- 将字串以tokenizer切割成一段段的短语
- 将phrase进行hash后存进表
- 搜寻时也将搜寻字串以tokenizer切割成一段段的短语,在哈希表中进行搜寻
举例而言,讯息qwert qaz qsc
在搜寻时只会分别匹配到qwert
, ,这qaz
三个qsc
字串,你搜寻单独的q
,a
,er
都不会匹配到。
那问题接着来了:标记生成器根据什么切割??用以切割阶段的字元,我们称之分离器或分隔符,而剩下构成相的字元称之令牌。进一步来说,依据的unicode的类别,属于大号*(字母),N *(数字)及Co(其他)预设为令牌,其余都被视为分隔符。
因此,我们终于找到Telegram不能搜寻中文讯息的根本原因了。原来,由于unicode CJK(中日韩表意文字)绝大部分都属于Lo类别,从而,汉字语汉字间没有任何分隔符,会被整串拿去哈希,从而导致搜寻无效。
结语
不小心就打了一堆堆废话呢,相信大家都知道Telegram不能搜寻中文讯息的原因了。解决的方法我有想到两种,其一是手动在汉字间插入不可见的分隔符,另一种是写个客制化的tokenizer。
于此将我的一点浅见拿来分享作为抛砖引玉,希望各位电神不吝指教。未来若有空我也十分希望能为Telegram社群贡献。
原文地址:https://medium.com/@nevik.w39/%E7%82%BA%E4%BB%80%E9%BA%BC-telegram-%E4%B8%8D%E8%83%BD%E6%90%9C%E5%B0%8B%E4%B8%AD%E6%96%87%E8%A8%8A%E6%81%AF-6b7d07690e6f
试试
有下载nicegram的方法吗 兄弟
第一步 点击右上角的放大镜 然后输入 @zwdhqun 去搜索 第二步 点击显示的第一个搜 然后再点击 Join 按提示完成验证进群 第三步 发送中文包 三个字 到群内,然后点击机器人回复的第一个 中文包 这个三个字 注意不需要下载 让你下载的都是病毒 第四步 选择频道推荐的最佳中文包 点击一下蓝色的链接 第五步 点击弹窗的 CHANGE 就成功切换到中文了 频道内的这些中文包都是完成度比较高的。