0

我正在研究從Redshift數據庫獲取數據的Django應用程序。寫給這個Redshift數據庫的人做出了一些奇怪的選擇。我想弄清楚如何處理它有串這樣的事實:Python,Unicode:使用格式錯誤的字符串

Let’s play! \xe2\x9a\xbd\xef\xb8\x8f 

隨着psycopg2我得到這些進入Python作爲

u'Let\u2019s play! \\xe2\\x9a\\xbd\\xef\\xb8\\x8f' 

我應該呈現此作爲

讓我們玩吧! 012️

它們以varchar(65535)存儲在Redshift表中。我使用pyscopg2將它們拖入應用程序後端(Django 1.11,Python 2.7)。它們在前端使用JavaScript進行渲染。

任何建議,將不勝感激 - 我找不出任何解決方案。

+1

你有[變爲亂碼(HTTPS ://en.wikipedia.org/wiki/Mojibake)。它有多種編碼。我不確定你是如何得到你在psycopg2中做的結果的,因爲我找不到可以返回結果的編碼器。獲得U + 2019代碼點意味着一個Windows-125x編碼器,但是它們中的任何一個都不會在Python中返回UTF-8剩餘部分而不會出錯。一個正確的UTF-8編碼字符串應該是''讓\ xe2 \ x80 \ x99s玩! \ xe2 \ x9a \ xbd \ xef \ xb8 \ x8f'' –

+0

哎呀,您對我從psycopg2獲得的信息是否正確。更新的問題。 –

回答

1

由於存在多種編碼(看起來像Windows-1252和十六進制轉義的UTF-8),如果這種混合是一致的,您可以嘗試後處理條目。

下面是一個正則表達式查找十六進制轉義序列,並用UTF-8解碼等同替換它們:

import re 

esc = re.compile(r'(?:\\x[0-9a-f]{2})+') 

def fixer(m): 
    return m.group().encode('latin1').decode('unicode-escape').encode('latin1').decode('utf8') 

s = u'Let\u2019s play! \\xe2\\x9a\\xbd\\xef\\xb8\\x8f' 
f = esc.sub(fixer,s) 
print repr(f) 
print f 

輸出:

u'Let\u2019s play! \u26bd\ufe0f' 
Let’s play! ⚽️ 
+0

這個作品,謝謝!接受這個答案。你能解釋爲什麼你要編碼,解碼,再編碼,再解碼嗎?我已經看到,作爲許多unicode解決方案的一部分,我不清楚爲什麼。 –

+1

@NathanHinchey您*將*編碼爲字節,*解碼爲Unicode。 '.encode('latin1')'是一種把U + 0000直接轉換爲U + 00FF到00-FF的技巧,因爲'latin1'字符集是Unicode的前256個編碼點。因此,從一個Unicode字符串開始,將它轉換爲字節以便能夠使用'unicode-escape'編解碼器,但結果是另一個Unicode字符串,因此再次編碼爲字節並解碼爲UTF8。 –