朋友翻出十年前的 QQ 空间,想把签名改回当年那种火星文,找了几个在线转换器,转出来一半是问号。他让我帮忙写个本地的,跑起来才发现问题不在规则。

这类转换器本质是一张字符映射表加逐字替换,真正坑人的是生僻字能不能显示。

映射表怎么建

常见的规则有几类:同音字替换,把「你」换成「伱」;偏旁拆分,把「爱」写成「愛」再加符号;还有形近字替换和颜文字拼接。整理成 JSON,左边是常用字,右边是候选数组,每次转换随机取一个,输出才不像模板刷出来的。

生僻字和扩展区

  • 基本区两万多字,转换器用的多是这一片
  • 扩展 B 区有六万多字,很多字体不支持,转出来是方框
  • 页面统一声明 UTF-8,数据库字段也要 utf8mb4,否则存进去就丢

代码就一段替换循环

JS 里把映射表建成对象,逐字查表,查不到原样输出,最后拼成字符串。别用正则整体替换,同音字一对多,正则会互相覆盖。需要保留原文时,先用占位符把字母数字抽出来,转完再塞回去。

为什么在线工具转出来是问号

多数是页面编码和接口编码不一致。前端 UTF-8 提交,后端按 GBK 解,生僻字直接变成替换字符。还有的站点把结果塞进 URL 参数,浏览器对非 ASCII 字符的编码处理各不相同,复制出来就乱。

更要紧的是别乱用

火星文放在昵称、签名里无伤大雅,放进正文会影响搜索和阅读。做站的人拿它批量生成标题,被搜索引擎判成低质内容的例子不少。

批量生成时怎么不重样

一次转换整段文字,同一个字每次都取同一个候选,看着像机器翻的。改成按位置取模或者按随机种子取,同一篇里同一个字的写法也要有变化。生成完再做一遍去重,连续三个字都是同音替换的,读起来特别假。

朋友那个工具一下午就写完了,映射表两百多条,够用。真正的工程量在收集那些字,写代码反倒是最省事的一步。