Почему python urllib2 urlopen возвращает что-то отличное от браузера при вызове API

Мне нужно регулярно получать и анализировать данные XML с веб-сайта в форме:

https://api.website.com/stuff/getCurrentData?security_key=blah

Я не могу опубликовать фактические соединения из-за безопасного характера данных. Когда я помещаю этот URL-адрес в свой браузер (Safari), я получаю возвращенный XML.

Когда я звоню через urllib2, я получаю мусор.

f = urllib2.urlopen("https://api.website.com/stuff/getCurrentData?security_key=blah") 
s = f.read()
f.close()
s
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xc5\x96mo\xda0\x10\xc7\xdf\xf7SX\xbc\xda4\x15\xc7y\x00R\xb9\xae\xfa\xb4U\x1a-\x150M{5y\xe1\x06V\x13\x079\x0e\x14>\xfd\x9c\x84\xb0\xd2\xa4S\xa4L\xe5\x95\xef\xeeo 

В этом посте Urloib взламывает urlopen на некоторых сайтах (например, StackApps api): возвращает результаты с мусором, похоже, похожая проблема, но он ссылается на JSON вместо XML. Следуя инструкциям по просмотру заголовков, я думаю, что мне возвращаются данные GZIP. {Я сделал предложенный тест, размещенный здесь}

req = urllib2.Request("https://api.website.com/stuff/getCurrentData?security_key=blah",
                      headers={'Accept-Encoding': 'gzip, identity'})
conn = urllib2.urlopen(req)
val = conn.read()
conn.close()
val[0:25]
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xc5\x96]o\xda0\x14\x86\xef\xfb+,\xae6M'

В этом посте было высказано предположение, что это может быть локальной проблемой, поэтому я попробовал пример сайта.

f = urllib2.urlopen("http://www.python.org")
s = f.read()
f.close()
s
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n\n\n<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n\n<head>\n  <meta http-equiv="content-type" content="text/html; charset=utf-8" />\n  <title>Python Programming Language &ndash; Official Website</title>\n  

Это работает просто отлично, поэтому я думаю, что это как-то связано с API сайта, к которому я на самом деле пытаюсь получить доступ.

Этот пост Почему текст, полученный со страниц, иногда выглядит как бред? предположил, что мне, возможно, нужно что-то сделать с "Селеном", но затем автор сказал, что проблема "сама себя исправила", что не помогает мне понять, что не так.

Я не могу использовать Python для загрузки защищенных данных? Нужно ли использовать что-то другое, кроме urlib2 и url open?

Я использую Python 2.7 на Mac OSX 10.7.5

2 ответа

Решение

Вы получаете сжатые данные в формате GZIP; сервер прямо говорит вам, что делает с Content-Encoding: gzip, Либо использовать zlib библиотека для распаковки данных:

import zlib

decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
data = decomp.decompress(val)

или используйте библиотеку, которая поддерживает прозрачную декомпрессию, если заголовки ответа указывают на использование сжатия, например requests,

'\x1f\x8b\' это действительно магический заголовок для gzip, так что вы получаете данные gzip обратно.

Во втором примере вы явно принимаете данные в кодировке gzip, измените их на 'Accept-Encoding': 'identity' и посмотреть, если это имеет значение.

Другие вопросы по тегам