Почему 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 – 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'
и посмотреть, если это имеет значение.