关于unicode:Python删除无效的ascii字符

Python removing invalid ascii characters

我最近编写了一个脚本,从PDF中提取所有书签,并将它们保存在docx文件中。它适用于90%的文件,但不幸的是有些文件似乎与Unicode有问题。

我在这样的列表中得到书签:

1
2
3
4
[[u'3. Mechatronik f\xfcr Doppelkupplungsgetriebe, Sicherungshalter B, Sicherung 14 auf Sicherungshalter C', 2],
[u'4. Geber f\xfcr Getriebeeingangsdrehzahl, Hydraulikdruckgeber 1 f\xfcr automatisches Getriebe, Magnetventil 2, Magnetventil \x04, Magnetventil 5', 2],
[u'5. W\xe4hlhebel, Schalter f\xfcr W\xe4hlhebel in P gesperrt, Magnet f\xfcr W\xe4hlhebelsperre', 2],
[u'6. W\xe4hlhebel, Geber 2 f\xfcr Antriebswellendrehzahl, W\xe4hlhebel-Positionsanzeige', 2]]

当我尝试运行函数时,我得到了错误:

1
ValueError('All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters',)

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from docx import Document

list1 = [[u'3. Mechatronik f\xfcr Doppelkupplungsgetriebe, Sicherungshalter B, Sicherung 14 auf Sicherungshalter C', 2],
    [u'4. Geber f\xfcr Getriebeeingangsdrehzahl, Hydraulikdruckgeber 1 f\xfcr automatisches Getriebe, Magnetventil 2, Magnetventil \x04, Magnetventil 5', 2],
    [u'5. W\xe4hlhebel, Schalter f\xfcr W\xe4hlhebel in P gesperrt, Magnet f\xfcr W\xe4hlhebelsperre', 2],
    [u'6. W\xe4hlhebel, Geber 2 f\xfcr Antriebswellendrehzahl, W\xe4hlhebel-Positionsanzeige', 2]]

def save_docx(list1):
document = Document('default.docx')
file = open("Error_Log.txt", 'w')
for i in list1:
    try:
        p = document.add_paragraph()
        p.add_run(i[0]).bold = True
    except Exception as e:
        file.write(repr(e) + '
'
)
file.close()
document.save('Bookmarks.docx')

save_docx(list1)

我猜问题出在\x0上,但我不知道如何在不破坏整个文档的情况下删除这样的部分。我尝试过不同的编码和其他我可以在网上找到的东西,但到目前为止没有任何效果。

任何帮助都将不胜感激!


您的假设似乎是正确的:\x04是一个控制字符,并且您的错误消息明确指出不允许控制。

在将控制字符添加到文档之前,可以从字符串中筛选出控制字符,这样可以解决问题。这可以通过python的unicodedata模块来实现,特别是unicodedata.category。要排除的类别以"c"开头(来自http://www.unicode.org/reports/tr44/gc_values_table),其中包含所有控制字符。

以下内容可以代替您当前的add_run行:

1
2
line = filter(lambda c: unicodedata.category(c)[0] != 'C', i[0])
p.add_run(line).bold = True

另外,在Unicode字符串中包含Unicode字符的典型方法是使用uxxxx,而不是使用xxx(其中,XXXX是Unicode码位的十六进制)。