【问题标题】:Data returned from urllib query is incorrectly encoded从 urllib 查询返回的数据编码不正确
【发布时间】:2019-07-28 11:07:40
【问题描述】:

我正在从谷歌图像中抓取一些数据,发现诸如“î”之类的字母被错误地解码。在这种情况下,'î' 变为 'î'。我已将来自 google 查询的数据存储在一个对象中,其格式为:

{"key":"value"}

但是,字典的值可以包含其他字符,例如:

{"key":"File:Blue tit (Cyanistes caeruleus), Parc du Rouge-Cloître, Brussels ( 32781868883).jpg"}

当我收到数据时,它的形式是

{"key":"File:Blue tit (Cyanistes caeruleus), Parc du Rouge-Clo\xc3\xaetre, Brussels ( 32781868883).jpg"}

所以当我尝试将其转换为字节并使用以下方法进行解码时:

decoded_obj = bytes(raw_obj, 'utf-8').decode('unicode_escape')

我得到了输出

{"key":"File:Blue tit (Cyanistes caeruleus), Parc du Rouge-Cloître, Brussels ( 32781868883).jpg"}

爬虫代码如下:

import urllib.request
import json

url = 'https://www.google.com/search?q=Blue+tit+(Cyanistes+caeruleus),+Parc+du+Rouge-Clo%C3%AEtre,+Brussels+(32781868883).jpg&source=lnms&tbm=isch&sa=X&ved=0ahUKEwiE8866stfjAhWBolwKHQ1YCdQQ_AUIESgB&biw=1920&bih=937'

headers = {}
headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request)
data = str(response.read())

start_line = data.find('class="rg_meta notranslate">')
start_obj = data.find('{', start_line + 1)
end_obj = data.find('</div>', start_obj + 1)
raw_obj = str(data[start_obj:end_obj])

decoded_obj = bytes(raw_obj, 'utf-8').decode('unicode_escape')
final_obj = json.loads(decoded_obj)

print(final_obj)

【问题讨论】:

  • 因此,您在字符串中获得了十六进制值。问题变成将这些十六进制值转换为 unicode,或者在您的情况下,由于 i 带有抑扬符,解码格式应该是 latin-1,而不是 unicode 转义。

标签: python python-3.x utf-8 character-encoding


【解决方案1】:

响应数据由 UTF-8 编码字节组成:

>>> response = urllib.request.urlopen(request)
>>> res = response.read()
>>> type(res)
<class 'bytes'>
>>> response.headers
<http.client.HTTPMessage object at 0x7ff6ea74ba90>
>>> response.headers['Content-type']                                                                                           
'text/html; charset=UTF-8'  

处理这个问题的正确方法是解码响应数据:

>>> data = response.read().decode('utf-8')

完成此操作后,data 即为 str,无需任何进一步的解码或编码(或 str() 或 bytes() 调用)。

一般来说,在bytes 实例上调用str 是错误的做法,除非您提供适当的编码:

>>> s = 'spam'
>>> bs = s.encode('utf-8')
>>> str(bs)
"b'spam'"   # Now 'b' is inside the string
>>> 

>>> str(bs, encoding='utf-8')
'spam'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多