【问题标题】:Read unicoded text from file not correctly, missing space, wrong character从文件中读取 unicode 文本不正确,缺少空格,错误字符
【发布时间】:2019-05-24 07:27:07
【问题描述】:

我正在清理 .txt 文件的文本。但是,在阅读文件后,我发现文本中只有一些单词之间缺少空格和错误的字符。

我使用的是 Python 3,文本是越南语。

Orignial text: "vui lòng cởi đồ ra tôi muốn nghe khám bệnh"
In[1]: with open('test.txt') as f:
          read_text = f.read()
       read_text
Out[1] vui lòng cởi đô`ra tôi muốn nghe khám bệnh

仔细看“đồ ra” -> “đô`ra”。一个字符“ồ”变成了两个字符:“ô”和“`”。

当我使用re 删除所有特殊字符时

In[2]: import re
       read_text = re.sub('\W+',' ',read_text)
       read_text
Out[2]: vui lo ng cơ i đô ra tôi muô n nghe kha m bê nh

结果应该和原来的一样,但是没有。怎么了?

【问题讨论】:

  • 我认为你需要包含编码。试试这个`with open('test.txt', encoding='utf-8')。检查此页面以获取 python 标准编码docs.python.org/2.4/lib/standard-encodings.html
  • 这可能与用于在终端中呈现文本的字体有关 - 并非所有字体都能正确处理组合字符。尝试其他一些对 unicode 友好的字体,看看它们是否能正确呈现文本。
  • @Nick 我试过了,但还是不行。
  • @AnhQuýLêGia 有问题的字符是复合字符。如果您复制它 (ồ) 并按一次退格键,您会注意到 ô 仍然存在。两个字符并排显示是控制台未正确处理 ` 与 ô 的副作用。 re 示例没有按预期工作,因为上面带有 ` 的其他字符也是复合的,但您的控制台可以正确显示。

标签: python python-3.x unicode fonts terminal


【解决方案1】:

问题不在于 Python 语言 - 问题是您指向的特定字符,可能还有其他字符,有两个组合的变音符号。问题是并非所有的文本处理应用程序都可以处理这个问题。我自己正在使用基于 Qt 的终端,在该终端中粘贴问题中的第一个字符串只是“取消”了第二个变音符号 - “`”标记,只留下“ô”。 (不过,基于 GTK+ 的终端可以正确处理它)。

所以问题是 Python 提供的 unicode 字符串是正确的。但是,您用来查看它的终端应用程序无法正确处理它,并将两个变音符号放在同一个字符上。

从 unicode 字符中过滤变音符号几乎从来都不是“正确的做法”。如果您的应用程序要支持越南语文本,它应该正确执行,而不是默默地转换某些字符。

对于“基于西方”的语言,字母通常会有一个更容易的变音符号 - 不仅终端和输出库支持很好,而且通常所有字符都由单个 unicode-codepoint 表示。

但是,当人们转向每个字符需要更多变音符号时,您就会失去“字符串中的一个字符”等于“屏幕上的一个字符”的等价性(无论输出是否正确)。然后你必须在你的代码中担心这一点。

如果您只是为搜索建立索引,甚至是用于训练的文本语料库,那么去掉变音符号可能是可以的,但是,也许,您应该去掉所有它们。

这样做的方法是强制将字符串转换为规范化的 Unicode 表示,其中所有变音符号都表示为单独的“组合字符”而不是组合字符,然后仅过滤掉字母字符;

import unicodedata
a = "vui lòng cởi đồ ra tôi muốn nghe khám bệnh"

# Normalize the internal representation:
b = unicodedata.normalize("NFKD", a)
print(*(c for c in b), sep=" ")
# outputs: "v u i   l o ̀ n g   c o ̛ ̉ i   đ o ̂ ̀   r a   t o ̂ i   m u o ̂ ́ n   n g h e   k h a ́ m   b e ̣ ̂ n h"

# recreates the string filtering out combining characters:
c = "".join(c for c in b if unicodedata.category(c) != "Mn")
print(c)
# outputs: 'vui long coi đo ra toi muon nghe kham benh'

【讨论】:

    猜你喜欢
    • 2021-12-21
    • 2018-06-22
    • 1970-01-01
    • 2011-01-19
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2016-02-02
    相关资源
    最近更新 更多