我从我正在使用的API(电报机器人)获取一些数据。 我正在使用与python-telegram-bot互动的Telegram Bot api库。 数据以JSON格式以UTF-8编码返回。 示例(摘录):
{'message': {'text': '\u200d\u200d\u200dhttp://google.com/æøå', 'entities': [{'type': 'url', 'length': 21, 'offset': 11}], 'message_id': 2655}}
可以看出,'entities'包含url类型的单个实体,它有一个长度和一个偏移量。 现在说我想在'text'属性中提取链接的url:
data = {'message': {'text': '\u200d\u200d\u200dhttp://google.com/æøå', 'entities': [{'type': 'url', 'length': 21, 'offset': 11}], 'message_id': 2655}}
entities = data['entities']
for entity in entities:
start = entity['offset']
end = start + entity['length']
print('Url: ', text[start:end])
然而,上面的代码会返回'://google.com/æøå'
,这显然不是实际的网址
原因是偏移量和长度是UTF-16码点。所以我的问题是:有没有办法在python中使用UTF-16代码点?我不需要能够计算它们。
我已经尝试过了:
text.encode('utf-8').decode('utf-16')
但是这会产生错误:UnicodeDecodeError: 'utf-16-le' codec can't decode byte 0xa5 in position 48: truncated data
非常感谢任何帮助。 我正在使用python 3.5,但是因为它是一个统一的库,所以在python 2.x中也可以使用它。
答案 0 :(得分:4)
Python已经将UTF-8编码的JSON数据正确解码为Python(Unicode)字符串,因此无需在此处理UTF-8。
您必须编码为UTF-16,取编码数据的长度,然后除以2。我编码为utf-16-le
或utf-16-be
以防止添加BOM:
>>> len(text.encode('utf-16-le')) // 2
32
要使用实体偏移,您可以编码为UTF-16,切片加倍偏移,然后再次解码:
text_utf16 = text.encode('utf-16-le')
for entity in entities:
start = entity['offset']
end = start + entity['length']
entity_text = text_utf16[start * 2:end * 2].decode('utf-16-le')
print('Url: ', entity_text)