2013-10-22 139 views
1

我一直在用Python進行解碼和編碼,我不知道如何解決我的問題。我使用美麗的湯來解析每個文件,然後查看文件中的任何句子是否包含來自兩個不同單詞列表的一個或多個單詞,從而循環顯示用utf-8編碼的xml文本文件(sample)。因爲xml文件來自十八世紀,所以我需要保留xml中的em破折號。下面的代碼可以做到這一點,但它也保留了我希望刪除的討厭的框角色。我相信箱子的角色是this character。在這個網頁上,這個字符看起來像一個'或'管道,但是當我在Komodo中讀取xml文件時,它看起來像一個盒子,當我試圖將盒子複製並粘貼到搜索引擎中時,它看起來像一個'或'管道,但當我打印到控制檯時,該字符看起來像一個空盒子。)Python:從字符串中刪除特定字符(u「 u2610」)

總而言之,下面的代碼運行時沒有錯誤,但它會打印我想要刪除的空框字符。

for work in glob.glob(pathtofiles): 

    openfile = open(work) 
    readfile = openfile.read() 
    stringfile = str(readfile) 

    decodefile = stringfile.decode('utf-8', 'strict') #is this the dodgy line? 
    soup = BeautifulSoup(decodefile) 

    textwithtags = soup.findAll('text') 

    textwithtagsasstring = str(textwithtags) 

    #this method strips everything between anglebrackets as it should 
    textwithouttags = stripTags(textwithtagsasstring) 

    #clean text 
    nonewlines = textwithouttags.replace("\n", " ") 
    noextrawhitespace = re.sub(' +',' ', nonewlines) 

    print noextrawhitespace #the boxes appear 

我嘗試用

noboxes = noextrawhitespace.replace(u"\u2610", "") 

除去箱子但是Python中拋出一個錯誤標誌:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 280: ordinal not in range(128) 

有誰知道我可以從XML文件中刪除的箱子?我會很感激別人可以提供的任何幫助。

+1

哇,誰是生成的XML文件在18世紀?萊布尼茨? – abarnert

+1

(萊布尼茨的確如此,但牛頓擊敗了他。) – duhaime

+1

同時,'str(readfile)'應該做什麼?文件的'read'方法已經返回一個'str'。 – abarnert

回答

3

問題是你在混合unicodestr。當你做到這一點,Python有使用sys.getdefaultencoding(),通常是ASCII,這是幾乎從來沒有你想要的一個轉換到另一個,這是不*

如果異常來源於此行:

noboxes = noextrawhitespace.replace(u"\u2610", "") 

...修復很簡單...除了您必須知道noextrawhitespace是否應該是unicode對象或UTF-8編碼str對象)。如果是前者,那就是:

noboxes = noextrawhitespace.replace(u"\u2610", u"") 

如果是後者,那就是:

noboxes = noextrawhitespace.replace(u"\u2610".encode('utf-8'), "") 

不過說真的,你必須讓所有在你的代碼相一致的字符串;將這兩者混合在一起會導致更多地方出現問題。


因爲我沒有你的XML文件來測試,我寫我自己:

<xml> 
    <text>abc&#9744;def</text> 
</xml> 

然後,我將這兩行代碼的底部(與位到頂部剛打開,而不是通配符無論什麼)我的文件:

noboxes = noextrawhitespace.replace(u"\u2610".encode('utf-8'), "") 
print noboxes 

現在的輸出是:

[<text>abc☐def</text>] 
[<text>abc☐def</text>] 
[<text>abcdef</text>] 

所以,我認爲這就是你想要的。


*當然有時你想ASCII ......但這些,當你有unicode對象...

+0

非常感謝您提供了有用的回覆,@abarnert。我花了一些時間,並且不得不做一些外部研究,看來當腳本到達打印行時,文本對象已經被轉換回ascii字符串(因爲'textwithtagsasstring'這一行,將文本轉換爲字符串,以便我可以運行removeNonAscii()方法,該方法將字符串作爲輸入。麻煩的是,我嘗試了所有您建議的三種方法,但討厭的方框仍在打印到控制檯。我錯過了嗎? – duhaime

+0

@duhaime:你真的是指「轉換回ascii字符串」,或「轉換回UTF-8字符串」嗎?因爲後者可以處理;前者,已經太遲了......無論如何,你是否試過我的測試代碼?它是否適用於你?你的XML看起來像這樣,還是直接存儲了un-charref轉義的Unicode?如果後者,你確定它是UTF-8?是文件中的實際字節?) – abarnert

+0

啊,我用'print isinstance(noextr然後用'import chardet'' print chardet.detect(noextrawhitespace)'得到'{'confidence':0.99,'encoding':'utf-8'}「。然後我用我的IDE編輯我的「當前文件設置」,並選擇「utf-8」作爲我的編碼。然後,我可以簡單地使用'noboxes = noextrawhitespace.replace('|','')',除了框看起來像IDE中的一個盒子。然後noboxes按預期打印。這是盜版解決方案嗎?會引入意想不到的問題嗎?我非常感謝你的評論。 – duhaime

2

試試這個:

noextrawhitespace.replace("\\u2610", "") 

我認爲你只是缺少額外的 '\'

這也可能工作。

print(noextrawhitespace.decode('unicode_escape').encode('ascii','ignore')) 
+0

非常感謝,@ jramirez,但我相信'.rstrip()'只會刪除noextrawhitespace對象後的任何空白字符。我相信我需要的東西像'.replace(boxcharacter,「」)'或者're.sub()'方法,它們可以讓我消除方塊字符。 – duhaime

+0

你說得對。我只是編輯了我的答案,也許這將起作用。 – jramirez

+0

再次感謝@jramirez。這種方法確實消除了盒子,但它也消除了我希望保留的em-dashes。有沒有辦法保持em-dashes,但消除框?我很感謝你的建議。 – duhaime

1

讀你的樣品通常不是時間,以下是文件中的非ASCII字符:

0x2223 DIVIDES 
0x2022 BULLET 
0x3009 RIGHT ANGLE BRACKET 
0x25aa BLACK SMALL SQUARE 
0x25ca LOZENGE 
0x3008 LEFT ANGLE BRACKET 
0x2014 EM DASH 
0x2026 HORIZONTAL ELLIPSIS 

\u2223是在線路3682的問題的實際的字符,它被用作一個軟連字符。其他人在標記用於標記亂碼,比如:

<GAP DESC="illegible" RESP="oxf" EXTENT="4+ letters" DISP="\u2022\u2022\u2022\u2022\u2026"/> 

下面是一些代碼做什麼你的代碼嘗試。確保以Unicode來處理:

from bs4 import BeautifulSoup 
import re 

with open('k000039.000.xml') as f: 
    soup = BeautifulSoup(f) # BS figures out the encoding 

text = u''.join(soup.strings)  # strings is a generator for just the text bits. 
text = re.sub(ur'\s+',ur' ',text) # Simplify all white space. 
text = text.replace(u'\u2223',u'') # Get rid of the DIVIDES character. 
print text 

輸出:

[[truncated]] reckon my self a Bridegroom too. Buckle. I doubt Kickey won't find him such. [Aside.] Mrs. Sago. Well,—poor Keckky's bound to good Behaviour, or she had lost quite her Puddy's Favour. Shall I for this repine at Fortune?—No. I'm glad at Heart that I'm forgiven so. Some Neighbours Wives have but too lately shown, When Spouse had left 'em all their Friends were flown. Then all you Wives that wou'd avoid my Fate. Remain contented with your present State FINIS.

+0

感謝您的反饋,@ Mark Tolonen。我嘗試實施您的建議,這似乎比我的Rube Goldberg方法快得多,但是當我嘗試寫入磁盤時出現錯誤。我試圖在每次滿足條件時寫入()'幾個製表符分隔的字段,後面跟一個''\ n'',但是試圖寫入'\ n'的行出現錯誤消息: 'UnicodeEncodeError:'ascii'編解碼器不能在位置0編碼字符u'\ u2014':序號不在範圍(128)'中。你碰巧知道我該如何解決這個錯誤?我會很感激你能提供的任何見解。 – duhaime

+0

使用'codecs.open'函數打開文件並指定編碼。這是將Unicode寫入文件的正確方法。 –