2016-12-07 118 views
0

我最近編寫了一個腳本來從PDF中提取所有書籤並將它們保存在docx文件中。它適用於90%的文件,但不幸的是有一些似乎與unicode有問題。刪除無效的ascii字符的Python

我得到一個列表中的書籤是這樣的:

[[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]] 

當我嘗試運行的功能我得到的錯誤:

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

代碼:

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) + '\n') 
file.close() 
document.save('Bookmarks.docx') 

save_docx(list1) 

林猜測問題是\x0但我不知道如何刪除這樣的部分,而不毀了整個d ocument。 我已經試過不同的編碼和其他任何我可以在網上找到,但沒有任何工作到目前爲止。

任何幫助將不勝感激!

+0

你試過這個嗎? 'i [0] .encode('utf-8')'基於http://stackoverflow.com/questions/5760936/handle-wrongly-encoded-character-in-python-unicode-string –

+0

yes嘗試以各種方式進行解碼和編碼,例如'我[0] .encode('ascii''忽略')'等等。沒有任何工作。也看了可能幫助但沒有運氣的圖書館。 – TacashiX

+0

@jackmorris的不錯答案。難道在編碼之後控制字符仍然在字符串中?因此最終結果將是相同的(error'no control characters') –

回答

0

您的假設似乎是正確的:\x04是一個控制字符,並且您的錯誤消息明確指出不允許控件。

您可以在將字符串添加到文檔之前過濾掉字符串中的控制字符,這可以解決您的問題。這可以用Python的unicodedata module完成,特別是unicodedata.category。您要排除的類別以'C'(從http://www.unicode.org/reports/tr44/#GC_Values_Table開始)開頭,其中包含所有控制字符。

以下應該工作,取代當前的add_run行:

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

順便說一句,其中包括一個Unicode字符串Unicode字符的典型方式是爲\ uXXXX,而不是\ XXX(其中XXXX是unicode代碼點的十六進制)。

+0

unicodedata返回的類別'\ x04'的類別是'Cc',而不是'C'。我不會說'\ uXXXX'符號是「典型」的方式,對於低於256的代碼點,'\ xXX','\ u00XX'和'\ U000000XX'之間沒有區別,並且python本身總是使用盡可能最短的形式,例如'python2中的'ascii(「\ U000000FF」)'(或'repr(u「\ U000000FF」)')給出'\ xff'。 – mata

+0

類別'C'包括'Cc'以及'Cf',它是格式控制字符。 –

+0

另一點,'典型'可能是錯誤的詞語,但我認爲將Unicode字符指定爲代碼點而不是字節值會更有意義,特別是當您超過256時。您說得對對低值代碼點沒有影響。 –