处理Unicode字符时如何避免丢失文本有效内容
问题背景
针对无现代标准正字法的古语言开展N-gram分析时遇到文本编码问题,对应古语言正字法样式如下:
初始采用如下代码读取Docx格式语料:
Text = docx2txt.process(Corpus) print(Text)
将读取到的文本存入字典后,输出内容包含Unicode转义字符,示例如下:
"daniel.mahabi": {"xq\u2019xucubaquibms.xqui\u00e7i\ua72dih": 1.0},
曾尝试通过ASCII编码过滤的方式修复问题:
Text = docx2txt.process(Corpus) Text = Text.encode("ascii", "ignore") Text = Text.decode()
该方案会同步移除文本中的古语言特殊正字法有效内容,无法满足需求。
问题根源
输出中出现的\u2019、\u00e7、\ua72d不属于读取错误,是Python打印字典、列表等内置容器时的默认机制:容器内的字符串会自动转义所有非ASCII Unicode字符为\uXXXX格式,不代表文本本身编码异常。
之前采用的ASCII编码+ignore参数的方案,会直接丢弃所有码位大于127的非ASCII字符,必然会丢失古语言正字法中的特殊字符,属于错误处理方式。
正确处理步骤
1. 验证文本读取结果是否正常
不要直接打印存储文本的字典对象,单独输出字符串片段即可验证读取结果是否正确:
import docx2txt corpus_path = "你的语料文件存储路径.docx" text = docx2txt.process(corpus_path) # 单独打印字符串内容,而非打印整个字典 print("文本片段预览:", text[:100])
如果该步骤输出的字符和原Docx中的古文字样式一致,说明docx2txt读取逻辑无问题,不需要额外做编码转换。
2. 解决字典输出转义问题
如果需要查看或存储字典中的N-gram统计结果,不要直接打印字典对象,采用以下两种方式即可正常显示所有特殊字符:
- 遍历字典逐元素打印,直接输出字符串原生内容:
ngram_result = {"daniel.mahabi": {"xq’xucubaquibms.xquiçiꜭdih": 1.0}} for file_tag, counter in ngram_result.items(): print(f"语料来源:{file_tag}") for ngram, freq in counter.items(): print(f" N-gram内容:{ngram},出现频率:{freq}")
- 序列化存储到文件时关闭ASCII转义,全程使用UTF-8编码:
import json with open("ngram统计结果.json", "w", encoding="utf-8") as f: # 指定ensure_ascii=False保留所有非ASCII特殊字符 json.dump(ngram_result, f, ensure_ascii=False, indent=2)
3. 特殊字符一致性校验
由于目标语言无标准现代正字法,建议读取完成后先统计所有出现的特殊字符,和原Docx内容做一致性核对:
from collections import Counter char_stat = Counter(text) # 输出所有非ASCII特殊字符的码位和出现次数 for char, cnt in char_stat.items(): if ord(char) > 127: print(f"特殊字符:{char},Unicode码位:U+{ord(char):04X},出现次数:{cnt}")
如果核对发现有字符和原文档不匹配,可更换为python-docx库逐段读取,避免docx2txt对特殊符号的错误转换:
from docx import Document doc = Document(corpus_path) text = "\n".join([para.text for para in doc.paragraphs])
处理全程所有文件读写操作统一使用
utf-8编码,禁止做任何ASCII编码转换,否则必然丢失古语言特殊正字法内容。
内容的提问来源于stack exchange,提问作者user3098629

