Как публиковать символы Юникода с помощью httplib?

Я пытаюсь опубликовать данные Unicode с помощью функции httplib.request:

s = u"עברית"
data = """
<spellrequest textalreadyclipped="0" ignoredups="1" ignoredigits="1" ignoreallcaps="0">
<text>%s</text>
</spellrequest>
""" % s

con = httplib.HTTPSConnection("www.google.com")
con.request("POST", "/tbproxy/spell?lang=he", data)
response = con.getresponse().read()

Однако это моя ошибка:

Traceback (most recent call last):
  File "C:\Scripts\iQuality\test.py", line 47, in <module>
    print spellFix(u"╫á╫נ╫¿╫ץ╫ר╫ץ")
  File "C:\Scripts\iQuality\test.py", line 26, in spellFix
    con.request("POST", "/tbproxy/spell?lang=%s" % lang, data)
  File "C:\Python27\lib\httplib.py", line 955, in request
    self._send_request(method, url, body, headers)
  File "C:\Python27\lib\httplib.py", line 989, in _send_request
    self.endheaders(body)
  File "C:\Python27\lib\httplib.py", line 951, in endheaders
    self._send_output(message_body)
  File "C:\Python27\lib\httplib.py", line 815, in _send_output
    self.send(message_body)
  File "C:\Python27\lib\httplib.py", line 787, in send
    self.sock.sendall(data)
  File "C:\Python27\lib\ssl.py", line 220, in sendall
    v = self.send(data[count:])
  File "C:\Python27\lib\ssl.py", line 189, in send
    v = self._sslobj.write(data)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 97-102: or
dinal not in range(128)

Где я не прав?


person iTayb    schedule 14.04.2012    source источник


Ответы (1)


http не определяется с точки зрения конкретной кодировки символов, а вместо этого использует октеты. Вам нужно преобразовать ваши данные в кодировку, а затем вам нужно сообщить серверу, какую кодировку вы использовали. Давайте использовать utf8, так как обычно это лучший выбор:

Эти данные немного похожи на XML, но вы пропускаете тег xml. Некоторые сервисы могут принять это, но вы в любом случае не должны. На самом деле, кодировка действительно принадлежит ему; поэтому убедитесь, что вы включили его. Заголовок выглядит как <?xml version="1.0" encoding="кодировка"?>.

s = u"עברית"
data_unicode = u"""<?xml version="1.0" encoding="UTF-8"?>
<spellrequest textalreadyclipped="0" ignoredups="1" ignoredigits="1" ignoreallcaps="0">
<text>%s</text>
</spellrequest>
""" % s

data_octets = data_unicode.encode('utf-8')

Из соображений вежливости вы также должны сообщить самому серверу формат и кодировку с заголовком content-type:

con = httplib.HTTPSConnection("www.google.com")
con.request("POST",
            "/tbproxy/spell?lang=he", 
            data_octets, {'content-type': 'text/xml; charset=utf-8'})

РЕДАКТИРОВАТЬ: На моей машине все работает нормально, вы уверены, что ничего не пропускаете? полный пример

>>> from cgi import escape
>>> from urllib import urlencode
>>> import httplib
>>> 
>>> template = u"""<?xml version="1.0" encoding="UTF-8"?>
... <spellrequest textalreadyclipped="0" ignoredups="1" ignoredigits="1" ignoreallcaps="0">
... <text>%s</text>
... </spellrequest>
... """
>>> 
>>> def chkspell(word, lang='en'):
...     data_octets = (template % escape(word)).encode('utf-8')
...     con = httplib.HTTPSConnection("www.google.com")
...     con.request("POST",
...         "/tbproxy/spell?" + urlencode({'lang': lang}),
...         data_octets,
...         {'content-type': 'text/xml; charset=utf-8'})
...     req = con.getresponse()
...     return req.read()
... 
>>> chkspell('baseball')
'<?xml version="1.0" encoding="UTF-8"?><spellresult error="0" clipped="0" charschecked="8"></spellresult>'
>>> chkspell(corpus, 'he')
'<?xml version="1.0" encoding="UTF-8"?><spellresult error="0" clipped="0" charschecked="5"></spellresult>'

Я заметил, что когда я вставил ваш пример, он отображается на моем терминале в порядке, обратном тому, как он отображается в моем браузере. Неудивительно, учитывая, что иврит — язык с письмом справа налево.

>>> corpus = u"עברית"
>>> print corpus[0]
ע
person SingleNegationElimination    schedule 14.04.2012
comment
Пропуск XML-декларации — это нормально. Он нужен только в том случае, если вам нужна кодировка, отличная от UTF, или XML 1.1. - person bobince; 14.04.2012
comment
Google фактически возвращает ошибку, если вы отправляете декларацию XML. - person iTayb; 14.04.2012
comment
@iTayb: Как выглядит ошибка? На моей машине работало нормально. - person SingleNegationElimination; 19.04.2012
comment
@TokenMacGuy, вот ответ, который я получаю: <?xml version="1.0" encoding="UTF-8"?><spellresult error="1"/> - person iTayb; 19.04.2012