2013-06-22 152 views
3

我有一個我想分析的XML文件的文件夾。我需要從這些文件的元素中獲取文本。它們將被收集並打印到一個CSV文件,其中的元素列在列中。Again:UnicodeEncodeError:ascii編解碼器無法編碼

可以實際上這樣做現在爲一些我的文件。也就是說,對於我的許多XML文件來說,這個過程很順利,並且我得到了我想要的輸出。執行此代碼是:

import os, re, csv, string, operator 
import xml.etree.cElementTree as ET 
import codecs 
def parseEO(doc): 
    #getting the basic structure 
    tree = ET.ElementTree(file=doc) 
    root = tree.getroot() 
    agencycodes = [] 
    rins = [] 
    titles =[] 
    elements = [agencycodes, rins, titles] 
    #pulling in the text from the fields 
    for elem in tree.iter(): 
     if elem.tag == "AGENCY_CODE": 
      agencycodes.append(int(elem.text)) 
     elif elem.tag == "RIN": 
      rins.append(elem.text) 
     elif elem.tag == "TITLE": 
      titles.append(elem.text) 
    with open('parsetest.csv', 'w') as f: 
     writer = csv.writer(f) 
     writer.writerows(zip(*elements)) 


parseEO('EO_file.xml')  

然而,在輸入文件的某些版本中,我得到了臭名昭著的錯誤:

'ascii' codec can't encode character u'\x97' in position 32: ordinal not in range(128) 

完整回溯是:

--------------------------------------------------------------------------- 
UnicodeEncodeError      Traceback (most recent call last) 
<ipython-input-15-28d095d44f02> in <module>() 
----> 1 execfile(r'/parsingtest.py') # PYTHON-MODE 

/Users/ian/Desktop/parsingtest.py in <module>() 
    91   writer.writerows(zip(*elements)) 
    92 
---> 93 parseEO('/EO_file.xml') 
    94 
    95 

/parsingtest.py in parseEO(doc) 
    89  with open('parsetest.csv', 'w') as f: 
    90   writer = csv.writer(f) 
---> 91   writer.writerows(zip(*elements)) 
    92 
    93 parseEO('/EO_file.xml') 
UnicodeEncodeError: 'ascii' codec can't encode character u'\x97' in position 32: ordinal not in range(128) 

我我相當有信心從閱讀其他線程中發現問題出在使用的編解碼器上(並且,你知道,錯誤也很明顯)。然而,我讀過的解決方案並沒有幫助(強調是因爲我明白我是問題的根源,而不是人們過去回答的方式)。

一些反饋(如:this onethis onethis one)不直接處理ElementTree,我不知道如何將解決方案轉換爲我正在做的。

那些處理ElementTree的(如:this onethis one)其他解決方案,要麼使用一個簡短的字符串(這裏的第一個鏈接),或正在使用的ToString/.fromstring在ElementTree的方法,我不知道。 (雖然,當然,也許我應該的。)

事情我都試過,沒有工作:

  1. 我試圖通過UTF-8編碼帶來的文件中:

    infile = codecs.open('/EO_file.xml', encoding="utf-8") 
    parseEO(infile) 
    

    但我認爲ElementTree過程已經將它理解爲UTF-8(這在我所有的XML文件的第一行中都有提到),所以這不僅不正確,而且實際上是非常糟糕的再次。

  2. 我試圖在循環中聲明的編碼處理,替換:

    tree = ET.ElementTree(file=doc) 
    

    parser = ET.XMLParser(encoding="utf-8") 
    tree = ET.parse(doc, parser=parser) 
    

    在環路上面確實工作。這對我也不起作用。之前工作過的相同文件仍然工作,創建該錯誤的相同文件仍然會產生錯誤。

已經有很多其他的隨機嘗試,但我不會說謊。因此,雖然我認爲我的代碼既沒有效率也沒有攻擊性,但它確實符合我對幾個文件的要求。我試圖瞭解是否有簡單的一個論點,我想念我不知道,如果我應該以某種方式預處理文件(我沒有確定哪裏是冒犯的角色,但知道你是' x97翻譯成某種控制字符)或其他選項。

回答

9

您正在解析XML; XML API傳遞給您的值爲unicode。然後,您試圖將unicode數據寫入一個CSV文件,而不是首先對其進行編碼。然後Python嘗試爲你編碼但失敗。你可以在你的回溯中看到這個,它是.writerows()調用失敗,並且錯誤告訴你編碼失敗,而不是解碼(解析XML)。

你需要選擇一個編碼,然後寫入之前編碼您的數據:

for elem in tree.iter(): 
    if elem.tag == "AGENCY_CODE": 
     agencycodes.append(int(elem.text)) 
    elif elem.tag == "RIN": 
     rins.append(elem.text.encode('utf8')) 
    elif elem.tag == "TITLE": 
     titles.append(elem.text.encode('utf8')) 

我用UTF8編碼,因爲它可以處理任何Unicode代碼點,但你需要使自己的,明確的選擇。

+0

完成並固定。完美工作。很多,非常感謝Martijn。 –

3

聽起來你在你的xml文件中有一個unicode字符。 Unicode與編碼爲utf8的字符串不同。

python2.7 csv庫不支持unicode字符,因此您必須通過函數對數據進行編碼,然後將其轉儲到您的csv文件中。

def normalize(s): 
    if type(s) == unicode: 
     return s.encode('utf8', 'ignore') 
    else: 
     return str(s) 

所以你的代碼應該是這樣的:

for elem in tree.iter(): 
    if elem.tag == "AGENCY_CODE": 
     agencycodes.append(int(elem.text)) 
    elif elem.tag == "RIN": 
     rins.append(normalize(elem.text)) 
    elif elem.tag == "TITLE": 
     titles.append(normalize(elem.text)) 
+0

非常感謝。 Martijn的建議是我嘗試的第一個建議,解決了我眼前的問題。這看起來像我可以從下一輪學到的東西。非常感謝您抽出寶貴時間。 –

+0

我花了很多時間(不幸)試圖調試Unicode錯誤。它花了一段時間讓我圍繞它思考!樂於幫助! – eblahm

+0

不要使用'type(s)== unicode';改用'isinstance(s,unicode)'。 –

相關問題