那页规格书在屏幕上是好好的泰语,机器复制走的是另一串字符
本文目录
- 同一份文件,人眼读到的和机器取到的为什么会是两串字?
- 一家园艺机械站的收录页面上,摘要那一栏是空的
- 复制粘贴那一下把问题暴露得最干净
- 它不是扫描件,这一点最容易被判错
- 把三类摆在一起,判断标准立刻变得可执行
- 文件里的字符流跟屏幕上的字形,是在哪一步脱钩的?
- 排版软件把字符换成了字形编号
- 子集化又给编号换了一套自家的号码
- 把号码翻回文字的那张表是可选的
- 字体内部那张对照表只朝一个方向工作
- 你手上这份文件属于哪一类,十秒钟怎么判出来?
- 第一招是复制粘贴,三秒钟出结果
- 第二招是在阅读器里搜一个词
- 第三招是命令行批量抽文字
- 第四招是直接看搜索引擎那一侧的结果
- 判完之后要把结论落到一张表上
- 每套书写系统坏起来,长的样子各不相同
- 阿拉伯语和波斯语:变形之后的形状被当成字符存了进去
- 希伯来语:顺序和元音标记两头都可能出事
- 天城文和泰米尔文:屏幕上的顺序跟存储顺序本来就不一样
- 泰语:上下叠的那两层记号最容易掉
- 中日韩:全角半角和竖排是两个独立的坑
- 越南语:两种码位写法会同时出现在一份文件里
- 拉丁字母为什么几乎从来不出这个事?
- 它的编号跟通用字符集天然对得上
- 唯一露过头的是那两个连字
- 德语的长复合词会把这件事放大
- 所以这件事从来没被当成一个类别
- 生成端的哪一步真正决定了这份文件能不能被读?
- 排版软件导出时的那两三个开关
- 用浏览器打印成文件的那条路要单独测
- 模板引擎批量生成的那条链路问题最集中
- 字体选择比导出设置更早决定结果
- 打标签这件事顺带解决了另外两个问题
- 已经发出去的那几百份,还救得回来吗?
- 先按能不能拿到源文件分两堆
- 第三条路是把文字搬到网页上
- 要不要换地址,这一步别急着动
- 修完之后怎么确认真的修好了
- 小语种内容到底该不该装进这种格式?
- 哪几类内容天生适合
- 哪几类放进去等于把流量埋了
- 一份内容两种载体怎么分工
- 下载量和自然流量是两笔账
- 标题、文件名和语言标记这三处该怎么填?
- 文档标题跟文件名不是一回事
- 文件名走拉丁转写这条老规矩
- 语言标记至少有三处要填
- 结构化数据那一侧要不要动
- 程序读到一串垃圾字符,比什么都读不到更糟
- 空白至少是诚实的
- 一串乱码会被当成内容对待
- 跟注音层那件事的差别在哪儿
- 哪些事不归这一层管
- 常见问题解答
- 不懂泰语,怎么自己判断一份泰语文件有没有问题?
- 为什么同一份文件在阅读器里看得好好的,抽出来就是乱码?
- 用识别的办法统一处理一遍,是不是更省事?
- 把资料全部改成网页,是不是就一劳永逸了?
- 这件事跟字体子集化冲突吗,为了修它要不要放弃子集化?
- 带标签的文件和普通文件,在检索上的差别有多大?
- 怎么防止新做的资料再犯同样的问题?
- 权威参考资料
摘要:一份泰语规格书在屏幕上一切正常,复制粘贴出来却是一串问号,搜索引擎抓走的也是同一串。它不是扫描件,它有文本层,只是那一层跟眼睛看到的字没有对应关系。根因在导出:字体子集化之后换了一套私有编号,而把编号翻回文字的那张对照表是可选项,很多工具默认不写。拉丁字母几乎撞不上,非拉丁文字则必须靠它。本文讲清三类文件十秒怎么判、各书写系统坏起来长什么样、生成端哪一步决定成败、发出去的几百份还救不救得回来。
同一份文件,人眼读到的和机器取到的为什么会是两串字?
一家园艺机械站的收录页面上,摘要那一栏是空的
有个客户做园艺机械,割草机、打药机、修枝工具这几条线。
德国总部出图纸和文案,各地分站翻译落地,泰国和越南两个市场做了两年。
产品资料一律做成可下载文件挂在站上,规格书、安装说明、保养手册,一款机器三四份。
这批文件在站内的内部链接给得很足,收录也没问题,站长工具里能查到它们躺在索引里。
问题出在收录之后:搜索结果里这些文件的标题是文件名,摘要那一栏是空的,一个字都没有。
更奇怪的是同一批文件的德语版一切正常,摘要里能看到规格表的前两行,泰语版和越南语版则是清一色的空白。团队最先怀疑的是抓取权限,查了一圈响应头和robots规则,全都正常,文件也确实被抓走了。真正的差别不在传输这一层,而在文件内部:抓走的东西里根本没有可读的文字。
复制粘贴那一下把问题暴露得最干净
排查的转折点很朴素,把那份泰语规格书打开,框选一段,复制,粘贴到记事本里。
屏幕上选中的是一整行泰语参数,粘贴出来是一行方块加问号,长度还对不上。
换德语版做同样的动作,粘出来一字不差。
这时候结论已经出来了:不是抓取问题,是这份文件里的文字取不出来。
保哥后来把这一步固化成了排查的第一动作,成本是三秒钟,能替掉半天的传输层排查。
顺带说一句,这个动作还有个副作用很有意思:它同时验了用户体验。采购这类机械的人有个很常见的习惯,把规格表复制到自己的比价表格里,粘出来是乱码的话,他不会给你发邮件报告问题,他会换一家。
这个动作还有一个变体值得一起做:把复制出来的字符串丢进任意一个能显示码位的工具,看那些字符落在哪个区间。落在正常的本地文字区间说明只是显示问题,落在私有区或者兼容区就说明写进文件的根本不是用户会打的那批字符。
它不是扫描件,这一点最容易被判错
业内讲这类文件的时候,习惯只分两类:一类是原生文字,一类是扫描出来的图片。
扫描件里没有文字,只有像素,所以要先做识别才能被检索到,这条大家都知道。
但这份泰语规格书不是扫描件,它是从排版软件直接导出的,屏幕上放大到八倍字形依然锐利。
它有文字层,能被选中,能被复制,只是复制出来的东西跟屏幕上的字对不上。
换句话说,它落在两类之外的第三类里,而站内已有的那套判断办法只准备了两个格子。
这个第三类的麻烦程度介于两者之间,却比两者都难被发现。扫描件一眼就能看出来,选不中文字,谁都会立刻明白该做识别;原生文字文件复制出来是对的,也没人操心。只有第三类能骗过所有人的眼睛,因为它在人这一侧表现得完美无缺。
判错的代价是排查方向整个走偏。团队一旦认定它是扫描件,接下来的动作就是上识别工具,跑完发现结果比原文还差,于是得出这个格式不适合做优化的结论,把整批资产判了死刑。真正的问题只需要改一个导出选项。
把三类摆在一起,判断标准立刻变得可执行
第一类是纯扫描图片,选不中文字,机器什么都读不到。
第二类是原生文字且映射完整,选得中、复制得出、机器读到的跟你看到的一致。
第三类是原生文字但映射缺失或错误,选得中、复制出来是垃圾、机器读到的也是垃圾。
三类的处理办法完全不同,第一类要识别,第二类什么都不用做,第三类要重新导出。
把这三格画进内容验收表,是整件事里最便宜的一次改动,一张表加一列而已。
这张三分表还有一个用法是给供应商提要求。产品资料经常由代理商或者本地经销商提供,验收标准里写清楚交付的文件必须落在第二类,比写一句要求文件清晰可读有用得多,因为后者双方理解不一致,前者可以当场验。
文件里的字符流跟屏幕上的字形,是在哪一步脱钩的?
排版软件把字符换成了字形编号
文字从输入到显示,中间有一道很多人没意识到的工序,叫字形排布。
这道工序的输入是字符,输出是字形编号加位置,负责的是排版引擎和字体里的规则表。
阿拉伯语的一个字母在词首词中词尾长得不一样,这道工序决定用哪一个形状。
天城文的元音符号要跑到辅音前面去,也是这道工序调换的位置。
这些工作做完之后,文档里存的已经不是你打进去的那些字符,而是一串编号。
把这套流程讲得最清楚的是开源排布引擎的说明文档,它明确写着输出的是字形而不是字符,而字形跟字符不是一一对应的关系——一个字符可能对应多个字形,多个字符也可能合并成一个字形。这句话正是整件事的根源,只是它写在一份字体工程的文档里,做内容和做优化的人基本不会翻到。
值得强调的是这道工序本身完全正确,它是所有非拉丁文字能正常显示的前提。阿拉伯语字母不做位置变形就没法读,天城文元音不重排就是错的。问题从来不在这道工序,而在它的产物被当成最终结果直接存了下来,中间少了一步回填。
子集化又给编号换了一套自家的号码
为了让文件别太大,导出时通常只嵌入用到的那些字形,这一步叫子集化。
子集化之后,字形在这份文件里的编号会被重排成一套连续的内部号码。
这套号码是这份文件私有的,换一份文件,同一个字的号码就变了。
页面渲染只需要按号码去取形状,所以显示完全正常。
但取文字的程序拿到的是这串私有号码,它没有任何办法据此还原出原来是哪个字。
小语种站为控制体积做子集化,本身是对的,字形集体积在非拉丁文字上确实是首屏的大头,这笔账在网页字体的字形集在小语种站上有多重那篇里算过。问题不在子集化,在子集化之后有没有补上那张翻译回来的表。
有一个现象可以佐证这套号码的私有性:把同一段文字分别导出成两份文件,用工具把内部编号打出来对比,两份的编号往往完全不同。同一个字在不同文件里是不同的号,这就是为什么外部工具不可能建一张通用的对照表来救。
把号码翻回文字的那张表是可选的
文件格式规范里为这件事准备了一个专门的结构,作用就是把内部号码映射回通用字符。
规范把它列为在需要抽取文字内容时应当提供的一项,而不是必须提供的一项。
于是它变成了一道选择题,交给导出工具的默认设置去回答。
有些工具默认写,有些默认不写,有些看你勾了哪个兼容级别才写。
而这道题的正确答案,跟你用哪种文字有直接关系。
这里有一个很容易被读反的地方:规范并没有写错,它写得很清楚,只是它把这件事定位成抽取文字时才需要的能力。二十年前,抽取文字确实是个边缘需求。今天,抽取文字就是被检索、被摘要、被引用的前提,它从边缘需求变成了主路径,而默认值还留在原地。
落到操作上,这一条意味着你不必去理解格式内部结构,只需要在导出环节确认这张表被写进去了。多数专业软件把它绑定在兼容级别或者标签选项上,勾了就有。真正危险的是那些没有任何相关选项的轻量工具,它们通常一律不写。
字体内部那张对照表只朝一个方向工作
字体文件里本来就有一张字符到字形的对照表,浏览器和排版引擎都靠它工作。
但这张表是单向的,它回答的是这个字该画成哪个形状。
反过来问这个形状原来是哪个字,表里没有这个方向的答案。
更麻烦的是替换规则会让多个字符合并成一个字形,反推在原理上就不成立。
所以取文字这件事没法靠字体自己解决,只能靠文件里另外补的那张表。
这条机制解释了一个长期让人困惑的现象:为什么同样一份文件,你用阅读器看得好好的,换一个工具抽文字就全是垃圾。因为看和抽走的是两条完全不同的路径,看走的是字形那条路,抽走的是字符那条路,而后一条路上的桥是可选建的。
顺带解释一个常见的误解:换一个更完整的字体救不了这件事。字体再完整,它提供的仍然只有单向映射。字体的完整度决定的是有没有字形可以显示,跟能不能把字形还原成字符是两个独立的问题,前者是显示层,后者是文档层。
你手上这份文件属于哪一类,十秒钟怎么判出来?
第一招是复制粘贴,三秒钟出结果
打开文件,框选一段正文,复制,粘贴到任意一个纯文本编辑器里。
粘出来跟屏幕上一致,说明映射完整,这一份不用管。
粘出来是问号、方块、乱码或者一片空白,说明映射缺失或错误。
完全选不中,那是扫描件,走识别那条路。
注意别粘到聊天窗口里试,那些地方会做自动清洗,看到的结果不可信。
做这一步的时候别只测一段。文件里不同区块可能出自不同的生成路径,正文是模板套出来的、表格是从表格软件粘进来的、页眉是图片,三者的表现常常不一样。至少测正文一段、表格一格、标题一行,三处都过了才算这一份没问题。
第二招是在阅读器里搜一个词
用阅读器自带的查找功能,输入正文里明明存在的一个词。
搜得到,说明文字层可用;搜不到,说明这一份取不出文字。
这一招比复制更接近搜索引擎的行为,因为它走的也是文字检索那条路。
做非拉丁文字的时候要挑一个不含数字和拉丁字母的纯本地文字词。
混着拉丁字母的词经常能搜到一半,那半个结果会把人误导到相反的结论上。
第三招是命令行批量抽文字
手上有几百份文件的时候,前两招显然不够用,得让机器跑。
开源的文档处理工具都提供把文字抽成纯文本的命令,一行就能跑一份。
把整个目录跑一遍,输出为空或者输出里非本地文字的比例过高的,就是问题文件。
这一步不需要写复杂逻辑,统计输出里落在本语言字符区间的字符占比就够用了。
占比阈值不用纠结,正常文件通常压倒性地高,问题文件通常接近于零,中间地带很少。
顺带提一句选型:能抽文字的开源库有好几套,行为略有差异,同一份文件有的能抽出来有的抽不出来。做批量体检的时候固定用一套就行,目的是找出问题文件,不是评测工具。
输出结果建议留档而不只是看一眼比例。抽出来的纯文本本身就是一份可搜索的语料,把它跟站内搜索日志里的高频词比对一遍,能顺手回答另一个问题:这批资料里到底有没有覆盖用户真正在搜的那些词。一次跑批,两个结论。
第四招是直接看搜索引擎那一侧的结果
前三招看的是文件本身,第四招看的是文件被读成了什么。
在搜索引擎里用文件地址查一下,看它给出的标题和摘要。
摘要空白或者摘要里全是乱码,说明抓走的东西同样不可读。
这一招的好处是它给的是最终结论,而且不依赖你本地装了什么工具。
它的缺点是慢,得等收录,所以适合复盘不适合上线前的验收。
判完之后要把结论落到一张表上
体检不落表,三个月后又要重做一遍,这是所有一次性排查的共同命运。
表里至少留四列:文件地址、语言、判定类别、处理动作。
再加一列生成来源,写清楚这份文件是从哪个软件哪条流水线出来的。
最后这一列是整张表里最值钱的,因为同一条流水线出来的文件通常一起坏。
修的时候也一起修,改一次导出设置能一次性带走几十份,比逐份处理省得多。
还有一列值得加:这份文件在站内有没有对应的网页。有网页的那些文件即使暂时修不好,检索这一侧的损失也有限;没有网页又不可读的文件,等于这部分内容在站上完全不存在。这一列直接决定修复的先后顺序。
每套书写系统坏起来,长的样子各不相同
阿拉伯语和波斯语:变形之后的形状被当成字符存了进去
阿拉伯字母按位置变形,同一个字母有独立、词首、词中、词尾四种形状。
通用字符集里为这些形状单独收录过一个兼容区,是历史遗留,正常文本不该用。
某些导出路径会把变形后的形状写进字符流,于是抽出来的是兼容区里的那些码位。
这种文本看着像本地文字,实际上跟用户在搜索框里打的字符串完全不是一批。
更糟的是它连不成词,检索匹配率接近于零,而肉眼几乎看不出问题。
阿拉伯语站上另一类高频问题是方向与折行,那属于版式层,跟这里说的字符层是两码事,阿拉伯语从右往左最容易翻车的那几处那篇讲的是前者,这一篇讲的是后者。两层都会让页面看起来出问题,但排查顺序必须是先字符后版式,反了会被表象带偏。
这一类的判别有个很省事的标志:抽出来的文本用普通的搜索框搜不到,但把它当字符串在文件里搜却能搜到。原因是两边用的码位不同,用户打的是正常字母,文件里存的是变形形状,两者在人眼里长得一模一样。
希伯来语:顺序和元音标记两头都可能出事
抽出来的希伯来语文本有时候是反着的,一整行从右往左倒排成字符序列。
这是因为导出时按视觉顺序写入,而不是按逻辑顺序。
视觉顺序的文本在屏幕上看没问题,进了检索就是一串谁也匹配不上的字符串。
另一头是元音标记,某些学术类和宗教类资料带标记,抽出来标记跑到了不该在的位置。
希伯来语本身不写元音这件事已经够让选词头疼了,希伯来语的三个辅音词根能对上七八个搜索词那篇算过这笔账,再叠一层顺序错乱就更没法查。
视觉顺序这个问题在老系统导出的文件里尤其常见,因为早期的排版方案就是靠预先把字符倒排来实现从右往左显示的。遇到明显是几年前生成的资料,这一项要单独测,不能用新文件的测试结果代表整批。
天城文和泰米尔文:屏幕上的顺序跟存储顺序本来就不一样
印度诸文字里,某些元音符号写在辅音左边,但在存储里它排在辅音后面。
排布引擎负责把它挪到左边显示,这是正常且正确的行为。
出事的是某些导出路径把挪完之后的显示顺序当成存储顺序写了进去。
结果是抽出来的字符串顺序被打乱,读起来像把每个音节都拆了重装。
印度市场的语言本来就摊在好几套书写系统上,印度十一门语言分摊在九套书写系统那篇算过预算要按后面那个数字走,这一层的体检同样要按书写系统而不是按语言排。
泰语:上下叠的那两层记号最容易掉
泰语的声调符号和某些元音符号叠在辅音上下方,一个音节可能摞三层。
抽文字时这几层有时候整层丢失,有时候顺序错乱,有时候被替换成近似字符。
丢掉之后剩下的辅音串依然是合法的泰语字符,所以任何合法性检查都会放行。
泰语的麻烦还叠了一层:它本来就不写空格,切词全靠词典。
记号一丢,词典就更切不动了,泰语标题里找不到一个空格,切在哪儿由引擎说了算那篇讲的分词困境会在这里被放大一倍。
还有一种更隐蔽的形态是记号还在但顺序错了。泰语的声调符号和元音符号有规定的存储次序,次序不对的字符串在屏幕上看不出差别,在检索里却是另一个词。这类问题只能靠跟原稿逐字比对发现,抽样时要专门挑带声调的词。
中日韩:全角半角和竖排是两个独立的坑
中日韩文字很少出现整片不可读,更常见的是局部替换。
全角的字母数字被抽成半角,或者反过来,导致规格型号对不上。
竖排文件抽出来的行序有时候是错的,尤其是竖排和横排混在同一页的时候。
日语还有一个专属问题,注音那一层会被拼进正文里,这件事单独讲过一遍。
页面上的注音层跟这里说的取文字问题是同一族的:显示是一回事,取值是另一回事,日语页面上那行给孩子读的小字被程序当成了正文那篇拆的是同一个机制在网页上的版本。
规格型号是这一类里损失最大的地方。型号本来就是用户最常直接复制的字符串,全角半角一混,复制出来的型号在搜索框里查不到任何东西。做工业品和电子品类的,这一项要单独抽检,而且要挑带字母数字混排的那些型号。
越南语:两种码位写法会同时出现在一份文件里
越南语的带记号字母有两种存储方式,一种是单个组合好的码位,一种是基字母加记号。
两种在屏幕上完全一样,在检索里是两个不同的字符串。
同一份文件里两种混着出现是常态,因为它取决于文字是从哪儿粘进去的。
抽出来之后如果不做归一,同一个词在你的语料里会被数成两个词。
越南语用户还有一半人根本不打声调符号,越南语要接的是两拨人,一半打声调另一半从不打那篇讲过匹配层要做双轨,那套双轨在处理文件抽出来的文本时同样得走一遍。
归一这件事要放在抽取之后立刻做,别等到进了索引再补。做法是把抽出来的文本统一转成同一种写法,转换规则是现成的标准算法,任何一门语言的开发库里都有。这一步跑完,同一个词才会在你的统计里只出现一次。
拉丁字母为什么几乎从来不出这个事?
它的编号跟通用字符集天然对得上
拉丁字母的编码历史让它占了个便宜:常用字母的码位跟老的单字节编码基本一致。
字体的默认编码方案也是围绕这一批字母建的,导出工具对它的处理路径最成熟。
于是即使那张翻译回来的表没写,工具也常常能靠标准编码猜对。
猜对的前提是这个字符在标准编码表里有位置,非拉丁文字大部分没有。
所以同一个工具,处理英语文件时表现完美,处理泰语文件时全军覆没。
唯一露过头的是那两个连字
拉丁世界唯一大规模遇到这个问题的地方,是排版连字。
某些字体会把相邻的两个字母合并成一个字形,最常见的是fi和fl这两组。
合并之后如果映射没补上,抽出来的是兼容区里的那个连字符号,而不是两个字母。
于是一个正常的英文词在检索里断成两截,中间多了一个谁也不认识的字符。
这件事在英语出版圈是个众所周知的老问题,解法也早就有了。
有意思的是这个老问题的规模:英语里受影响的只有几组字母,占全部文本的比例极小,改不改都不影响大局。所以它一直被当成一个排版细节而不是一个类别。等同一个机制换到非拉丁文字上,受影响的是全部文本,而方法论那一侧还停在把它当细节的阶段。
顺带记一个可以直接拿去用的检查项:在抽出来的英文文本里搜一下有没有出现连字的那几个码位。有的话说明这条生成链路会把合并后的字形写进字符流,那么同一条链路生成的非拉丁文字文件几乎必然有更严重的问题,可以直接排到修复队列前面。
德语的长复合词会把这件事放大
德语的复合词长,一个词里出现连字组合的概率自然比英语高。
词一旦在中间断开,剩下的两截都不是真实存在的词。
德语站上还有另一类看不见的断词字符,那是前端为了排版塞进去的,机制不同但后果相似。
两件事叠在一起,同一个词能被切出三四种不同的碎片。
那一类字符的排查办法在为了让德语长词在手机上不撑破,前端往标题里塞了个看不见的字符那篇里写过,扫描脚本可以直接复用,只是扫描对象从页面换成了文件。
德语还有一个叠加因素是断词符号。长复合词在窄栏里会被自动断开并插入连字符,某些导出路径会把这个排版用的连字符当成正文字符写进去。于是一个词在字符流里带着一个原文没有的符号,检索时自然对不上。
所以这件事从来没被当成一个类别
整套文档优化的方法论是拿英语写出来的,这一点在很多地方都成立。
英语作者遇到的是几组连字,于是文档里写的是注意连字。
非拉丁文字作者遇到的是整份文件不可读,而文档里没有对应的条目。
这不是谁疏忽,是样本决定的:写规范的人没见过整片失效的情形。
你能做的是把它补成一个类别写进自己的验收表,别指望通用清单里会有这一条。
把它写进自己的验收表时,措辞要具体到可执行。写检查文件可读性没有用,写抽取文本中目标语言字符占比不低于某个阈值才有用。前者是态度,后者是判据,而这件事在人眼里完全不可见,只有判据能拦住它。
生成端的哪一步真正决定了这份文件能不能被读?
排版软件导出时的那两三个开关
专业排版软件的导出对话框里,跟这件事相关的选项通常有三处。
一是兼容级别,选较新的级别通常会把映射表一起写进去。
二是是否创建带标签的结构,打了标签的文件在文字抽取上明显更稳。
三是字体嵌入方式,完整嵌入比子集化保险,代价是文件变大。
三处的默认值都不是为非拉丁文字准备的,所以模板要在项目开始时就定好。
用浏览器打印成文件的那条路要单独测
很多站的资料是用网页模板生成再打印成文件的,这条路省事,也确实常用。
它的表现取决于浏览器和系统字体,同一份网页在两台机器上能导出两种结果。
最常见的翻车是服务器上没装对应语言的字体,回退到了一个覆盖不全的字体。
屏幕上看是方块,导出的文件里那些字符干脆就没有。
这条链路的体检必须在真实的生成环境上做,本机测通不算数。
这条链路还有一个容易忽略的细节:网页上用的字体如果是通过网络加载的,生成环境能不能访问到那个地址直接决定结果。很多批量生成任务跑在没有外网的机器上,字体加载失败之后静默回退,生成的文件在测试环境完全正常。
模板引擎批量生成的那条链路问题最集中
规格书这类文件通常是从数据库里取数据套模板批量生成的,一次生成几百份。
批量生成的好处是一致,坏处也是一致:错了就是几百份一起错。
这类链路里最常见的问题是字体配置写死在模板里,加语言的时候没人改。
加一门语言相当于加一套文字,而模板里那行字体配置还停在项目启动那天。
模板这件事在多语言站上是个通用风险源,一个模板生成十种语言,信息层十份一模一样那篇讲的是内容侧的塌陷,这里是渲染侧的塌陷,两者共用同一个根因:模板的变量位留够了,语言参数没留够。
批量链路的修复反而是最划算的,因为改一处配置能一次带走几百份文件。所以体检表里那一列生成来源要填得尽量细,细到能定位是哪个模板哪个版本。填到这个粒度,修复工作量往往从几百份文件塌缩成三五处配置。
字体选择比导出设置更早决定结果
导出设置能补救的前提是字体本身规矩。
字体规矩的意思是它的字符到字形映射完整,没有大量私有区字符。
有些装饰性字体和老字体把字符塞在私有区,那部分从原理上就还原不回来。
私有区的字符在任何标准里都没有含义,抽出来只能是问号。
所以字体选型要在项目最前面做,做完之后拿一份真实内容跑一次完整体检。
选型阶段有个成本很低的验证动作:用候选字体排一段真实内容,导出一份文件,跑一遍抽取。这一步花不了半小时,却能在项目启动前就排除掉那些注定要返工的字体。等到几百份资料都做完再发现字体有问题,返工成本是另一个量级。
打标签这件事顺带解决了另外两个问题
带标签的文件会记录内容的逻辑结构,标题是标题,表格是表格。
这件事最初是为无障碍做的,读屏软件靠它决定读的顺序。
顺带的好处是抽文字时的顺序也跟着变可靠,多栏排版尤其明显。
规格书通常是多栏加表格,不打标签抽出来的顺序经常是串的。
所以给非拉丁文字资料打标签是一次投入换三份收益:无障碍、抽取顺序、检索质量。
要注意打标签不能替代映射表。带标签的文件结构清楚,但如果映射表缺失,抽出来的仍然是垃圾,只是垃圾排得整整齐齐。两件事各管一段:标签管顺序和结构,映射表管字符本身,缺哪一个都不行。
已经发出去的那几百份,还救得回来吗?
先按能不能拿到源文件分两堆
能拿到源文件的那堆最好办,改导出设置重新生成就行。
拿不到源文件的那堆要走识别,把文件当图片重新读一遍。
识别的准确率在非拉丁文字上参差不齐,规格表这类结构化内容尤其容易串行。
所以第二堆的处理成本比第一堆高一个数量级,能找到源文件就别省这个力气。
分堆之前先排优先级,按下载量和入口链接数排,别按文件数量平摊人力。
找源文件这件事值得多花点力气。产品资料的源文件通常散在设计外包、代理商和历任负责人的硬盘里,翻一遍的成本是几天,而它决定了后面是走几分钟的重新导出还是走按份计价的识别。这笔账在文件数量上百的时候差距非常明显。
第三条路是把文字搬到网页上
有一类文件既拿不到源文件,识别成本又不划算,比如老型号的资料。
这时候更划算的做法是把关键内容重新写成网页,文件本身保留供下载。
网页承接检索,文件承接下载,各干各的活。
这条路的额外好处是网页可以随时更新,而文件一旦发出去就很难追回。
做这件事的时候别把网页做成纯粹的下载页,那样等于把内容又埋了一次。
搬的时候优先搬三样东西:规格参数表、常见问题、以及型号和配件对照。这三样是用户最常搜也最常复制的内容,搬完之后即使原文件仍然不可读,检索这一侧的损失也基本被兜住了。其余的图示和安装步骤可以留在文件里。
要不要换地址,这一步别急着动
修好之后原地替换是首选,地址不变,已有的链接和收录都保得住。
只有在文件名本身就有问题的时候才考虑换地址,比如文件名是一串编码。
换地址要配跳转,规则跟页面搬家是同一套,这里不展开。
文件名该用本地文字还是拉丁转写,小语种地址用本地字母还是拉丁转写那篇给过判据,结论在文件上同样成立。
顺带提醒一句,替换之后记得让抓取重新跑一遍,否则索引里那份不可读的版本会继续挂着。
修完之后怎么确认真的修好了
验收动作跟体检动作是同一套,复制粘贴加命令行抽文字。
抽出来的文字要跟原稿逐字比对一段,别只看有没有输出。
有输出但内容错乱的情况在多栏排版里很常见,光看非空是判不出来的。
最后再等一轮收录,看搜索结果里的摘要有没有变成正常文字。
这一轮验完,才算真的闭环,前面几步都只是自己这边的确认。
建议把验收做成一份可复跑的脚本而不是一次性的人工核对。脚本每月跑一次全量文件目录,输出不合格清单。资料这类资产的特点是持续新增,一次性清理干净之后,半年内又会因为新链路上线而重新长出问题文件。
小语种内容到底该不该装进这种格式?
哪几类内容天生适合
需要精确排版并且要被打印出来的内容,天生适合这个格式。
安装图、接线图、尺寸图、保修卡,这些东西的价值就在于版式固定。
合规文件和认证证书也是,它们需要的是不可篡改的呈现而不是检索。
这类内容不用纠结检索问题,它们本来就不承担获取流量的任务。
但它们仍然要做体检,因为用户复制型号和参数是很常见的动作。
哪几类放进去等于把流量埋了
选型指南、对比说明、常见问题、保养建议,这几类是典型的埋流量。
它们的内容天生适合被检索,放进文件之后要多过一道抽取的关。
而这道关在非拉丁文字上的通过率,前面已经讲得够多了。
更现实的一点是,用户在手机上打开这类文件的体验普遍很差。
小语种市场的移动端占比通常更高,这笔账在移动端还要再乘一次。
判断某一类内容该不该放进文件,有个很直接的问法:这份内容存在的目的是让人读到,还是让人打印出来。目的是被读到的,就该以网页为主;目的是被打印或者归档的,才该以文件为主。这个问题问出来,多数分类当场就有答案。
一份内容两种载体怎么分工
最稳的做法是网页承载全文,文件承载可打印版本。
两者内容一致,网页在前,文件作为下载入口挂在网页里。
这样检索走网页,打印走文件,两条路互不打架。
要避免的是只有文件没有网页,那等于把内容押在抽取这一道关上。
也要避免网页只放一句简介加一个下载按钮,那样检索侧拿到的信息量近乎为零。
下载量和自然流量是两笔账
文件的下载量往往很好看,尤其是工业品类。
但下载量高不等于这批内容在获取新访客,很多下载来自已经找到你的人。
要判断它有没有带来新访客,得看有多少访问是从搜索结果直接落到文件上的。
这个数在非拉丁文字站上通常低得吓人,而原因往往就是本文讲的这一件事。
把这个数单独拉一列出来看,是说服团队投入修复的最快办法,比讲原理管用得多。
拆这个数的时候顺便看一眼落地路径:从搜索结果直接落到文件上的访问,有没有后续的站内浏览。多数情况下这个后续转化很低,因为用户落在一份文件里之后没有导航可用。这也从另一个角度说明为什么把内容锁在文件里不划算。
标题、文件名和语言标记这三处该怎么填?
文档标题跟文件名不是一回事
文件内部有一个标题属性,搜索结果里优先显示的是它而不是文件名。
这个属性经常是空的,或者留着模板里的默认值,比如未命名文档。
填它的成本几乎为零,收益是搜索结果里那一行字变成人话。
批量生成的链路上,这个属性应当跟着数据一起填,别留给人工。
顺带一提,很多批量生成的文件标题写的是数据库里的产品编码,那跟未命名的差别不大。
批量生成的时候,这个属性最好按一个固定模板填:产品名加文档类型加语言。这样搜索结果里那一行既能读懂又有区分度,用户在下载文件夹里也能一眼分清同一款产品的三四份资料。成本是模板里加一行拼接。
文件名走拉丁转写这条老规矩
文件名用本地文字会在地址里变成一长串编码,日志和外链里全是乱码。
这条规矩在页面地址上已经成立多年,在文件上完全一样。
文件名走转写,标题属性用本地文字,两处分工正好互补。
这跟商品图那六个能写字的位置是同一套思路,同一张商品图的文件名和替代文本要用两套字母写同一个词那篇把位置分层讲得最细,文件资产可以照着那张表再画一张。
语言标记至少有三处要填
文件内部有语言属性,页面上的链接可以带语言提示,页面本身也有语言声明。
三处填一致,抓取那一侧判断语言的把握就大得多。
短文本页面本来就容易被判成另一门语言,文件也一样,抽出来的文本越少判错概率越高。
判断语言归属其实可以靠字符层的证据,两种语言都看得懂的用户而你的站只能有一套地址那篇里讲过怎么用几个互不重叠的字母做语言识别,同一套办法用在文件抽出来的文本上一样成立,前提是那串文本本身是可读的。
这几处填不一致的时候,最容易出问题的是文件内部那一处,因为它经常保留着模板的默认值,通常是英语。一份泰语资料的内部语言标记写着英语,抽出来的文本又不可读,两个错误叠加,判定结果基本上就是随机的。
结构化数据那一侧要不要动
产品页上如果引用了这些文件,可以在标记里给出下载地址和格式。
标记里的语言字段按国际格式填,正文按本地习惯写,这两件事的方向是相反的。
这条反直觉的规矩在正文越本地化越好,结构化数据里却要反着写回国际格式那篇里拆过,文件字段照着同一套走就行。
不建议为不可读的文件补一堆标记,那是给一份读不出内容的资产加装饰。
顺序应该是先修文件,再补标记,反过来做等于把资源花在最没有杠杆的地方。
程序读到一串垃圾字符,比什么都读不到更糟
空白至少是诚实的
扫描件读不出内容,抓取那一侧拿到的是空,处理逻辑很干脆:没有内容。
没有内容意味着这份资产不参与匹配,损失是它本可以带来的那部分流量。
损失明确,边界清楚,也容易被发现。
不可读的文字层则不同,它给出的是一串看起来像文本的字符。
看起来像文本的东西会被当成文本处理,这才是问题的开始。
这条对比可以推广成一条更一般的判断:在内容质量的排查里,缺失通常比错误好处理,因为缺失是自证的而错误需要被识别。凡是产物看起来完整、格式合法、只是含义不对的问题,都要专门设计判据去逮,指望它自己暴露是不现实的。
一串乱码会被当成内容对待
抓到的字符会进入索引,会参与语言判定,会被当成这个页面的内容特征。
一份泰语规格书抽出来是兼容区字符,语言判定可能给出一个莫名其妙的结论。
更麻烦的是同一批文件抽出来的乱码高度相似,因为它们出自同一套内部编号。
高度相似的内容会触发重复判定,于是几百份资料被折叠成一份。
而你在报表上看到的现象是这批文件的收录量莫名其妙地掉,原因却根本不在内容上。
重复判定这一层的连锁反应最容易被误诊。报表上看到的是这批资料收录量下滑,最自然的猜测是内容质量或者抓取预算,很少有人会想到根因在字符层。这也是为什么值得把文件的抽取体检做成常规项,它能在诊断链条的最前端就把这条路排除掉。
跟注音层那件事的差别在哪儿
注音那件事是同一个位置摞了两串字,两串都是真的字,只是不该拼在一起。
这件事是同一个位置只有一串字,而这串字跟屏幕上显示的没有关系。
前者是多了一层要分流,后者是这一层根本对不上要重做。
两者的共同点是所有以合法性为判据的检查都会放行,因为产物在格式上完全合法。
这条规律在小语种的技术层问题里反复出现:真正难查的从来不是格式错误,而是格式正确但含义错位的东西,机器不报错,人也看不出来,只能靠专门设计的判据去逮。
两件事还有一个共同的实操结论:判断显示正常与否毫无意义,必须去看取值那一侧。网页上的做法是读取节点的文本内容,文件上的做法是抽取纯文本,动作不同但问的是同一个问题——机器眼里这一页到底写了什么。
哪些事不归这一层管
文件加载慢、体积大、移动端阅读体验差,这些是资产管理和性能的事。
要不要用下载表单换取联系方式,那是获客策略的事。
文件的版本管理和过期资料下架,那是内容运营的事。
这一篇只回答一件事:这份文件里的文字,机器能不能正确地取出来。
把这件事跟上面几件分开,排查的时候才不会在第一步就走进另一个部门的地盘。
常见问题解答
不懂泰语,怎么自己判断一份泰语文件有没有问题?
完全不需要懂那门语言。打开文件,选中正文里的一段,复制,粘贴到纯文本编辑器里,然后做一件事:把粘贴出来的字符串跟屏幕上的字对一下长度和形状。你不需要认识那些字,只需要判断它们看起来是不是同一批符号。粘出来是问号、方块或者空白,就是有问题;粘出来是一串跟屏幕上长得一样的字符,就没问题。
更省事的办法是让机器判:把文件抽成纯文本,统计输出里落在泰文字符区间的字符占多大比例。正常文件这个比例压倒性地高,问题文件接近于零。这个判据对任何一门你不认识的语言都成立,需要的只是知道那门语言的字符区间,查一次通用字符集的分区表就有。
为什么同一份文件在阅读器里看得好好的,抽出来就是乱码?
因为看和抽走的是两条不同的路。看这条路只需要知道每个编号该画成什么形状,字体里带着这个信息,所以永远不会出错。抽这条路需要知道每个编号原来是哪个字符,这个信息不在字体里,得靠文件生成时另外补一张对照表。这张表在规范里是抽取文字时才需要提供的,很多导出工具默认不写。
所以显示正常完全不能作为文件健康的证据。这也是为什么这类问题能活很久:负责做资料的人天天在看这些文件,从来没觉得有什么不对。要发现它,必须有人做一次显示之外的动作,而复制粘贴恰好是成本最低的那个动作。
用识别的办法统一处理一遍,是不是更省事?
不建议当成首选。识别是把文件当图片重新读一遍,它能绕开映射缺失的问题,但会引入新的错误,尤其是在规格表这种密集数字和型号的内容上。串行、认错小数点、把型号里的字母数字混淆,这几类错误在识别结果里很常见,而它们恰好落在最不该出错的地方。
正确的顺序是先分堆:能拿到源文件的重新导出,这条路准确率是百分之百;拿不到源文件又确实值得救的,才走识别,而且识别完要人工抽检关键数值。识别更适合处理真正的历史扫描件,对本文讲的这一类问题,它是备选方案不是主方案。
把资料全部改成网页,是不是就一劳永逸了?
检索这一侧确实一劳永逸,但会丢掉这个格式真正的价值。安装图、尺寸图、保修卡这类内容的价值在于版式固定和可打印,改成网页反而是降级。工业品类的采购流程里,把一份规格书打印出来带进会议室仍然是常见动作,这件事没法用网页替代。
更合理的形态是两者并存且分工明确:网页承载全文并负责检索,文件承载可打印版本并挂在网页里。要避免的两种极端是只有文件没有网页,以及网页上只放一句简介加一个下载按钮。后一种看起来两者都有,实际上检索侧拿到的信息量跟没有网页差不多。
这件事跟字体子集化冲突吗,为了修它要不要放弃子集化?
不冲突,两件事可以同时做。子集化解决的是体积,映射表解决的是可读性,一份文件完全可以既做了子集化又带着完整的映射表。所以不需要为了修这个问题去放弃体积优化,需要的只是在导出设置里把那张表打开。
要注意的是有些老工具确实做不到两者兼得,遇到这种情况优先保可读性。理由很简单:资料文件的体积问题主要影响下载速度,而下载发生在用户已经找到你之后;可读性问题影响的是用户能不能找到你。两个问题的先后顺序很清楚,先解决把人带进来的那个。
带标签的文件和普通文件,在检索上的差别有多大?
差别主要体现在结构复杂的文件上。单栏纯文字的文件,打不打标签抽出来的结果差不多。多栏排版、带表格、图文混排的文件差别就很明显,不打标签抽出来的顺序经常是串的,一段话的后半句接到了另一栏的开头。规格书恰好是结构最复杂的那一类,所以它从打标签里得到的收益最大。
另外打标签这件事本来是为无障碍做的,读屏软件靠它决定朗读顺序。所以这一次投入同时买到三样东西:无障碍合规、抽取顺序正确、检索质量提升。在需要满足无障碍要求的市场里,这笔投入本来就要花,顺带把检索这一侧的问题解决掉,性价比是整件事里最高的。
怎么防止新做的资料再犯同样的问题?
把它变成流水线的一道自动检查,而不是一份人工清单。具体做法是在文件发布的环节加一步:抽文字,统计目标语言字符占比,低于阈值直接拦下不许上线。这一步跑一份文件不到一秒,接进现有的发布流程几乎没有成本,而它能一劳永逸地挡住整条链路上所有的回归。
人工清单在这件事上不可靠,原因是这个问题在人眼里完全不可见。清单上写着检查文件可读性,执行的人打开文件看了一眼,觉得没问题,就打了勾。要让检查真的发生,判据必须是机器能执行的那种,而这个判据恰好非常好写。
本文标题:《那页规格书在屏幕上是好好的泰语,机器复制走的是另一串字符》
本文链接:https://zhangwenbao.com/minor-language-pdf-text-layer-extraction-failure.html
版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0