2013-05-31 15 views
0

我需要经常从形式的网站,获取并解析XML数据:为什么蟒蛇的urllib2的urlopen返回的东西从浏览器不同的API调用

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 

这篇文章Urllib's urlopen breaking on some sites (e.g. StackApps api): returns garbage results似乎是一个类似的问题,但它指的是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有关。

此帖子Why does text retrieved from pages sometimes look like gibberish?建议我可能需要用“Selenium”做点什么,但是那时海报说这个问题“固定了自己”,这并不能帮助我找出问题所在。

我无法使用python下载安全数据吗? 除了urlib2和url打开之外,我需要使用不同的东西吗?

我在Mac OSX上运行的Python 2.7 10.7.5

+0

检查标题;服务器是否返回*压缩*数据? –

+0

我不知道你的意思,@MartijnPieters - 我还是这个新手。但是......当我要求标题时,这就是我要求的标题''接受编码':'gzip,identity'}' – jessi

+0

这些是你发送的标题。请检查'conn.info()。headers'。 –

回答

2

您正在检索GZIPped压缩数据;服务器明确告诉你它与Content-Encoding: gzip。要么使用zlib库来解压缩数据:

import zlib 

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

或使用支持透明减压如果响应标头指示压缩已被使用,像requests库。

+0

优秀! zlib可以工作,但我会追查可能是更干净的解决方案的请求。我早些时候尝试了解请求,但我并不完全确定这会比'urllib2'和'urlopen'更好。 – jessi

+0

@Jessi:'requests'远比'urllib2'清洁。 :-) –

1

'\x1f\x8b\'确实是gzip的魔法头,所以你得到的gzip回数据。

在第二个例子中,你明确接受gzip的编码数据,更改到'Accept-Encoding': 'identity',看看它是否有差别。

+0

当我在接受中删除gzip时,@LennartRegebro获得了相同的东西。 'req = urllib2.Request(“https://api.website.us/stuff/getCurrentData?security_key=blah”, headers = {'Accept-Encoding':'identity'}) conn = urllib2.urlopen( req) val = conn.read() conn。close() val [0:25] '\ x1f \ x8b \ x08 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x03 \ xc5 \ x96Qo \ xda0 \ x10 \ xc7 \ xdf \ xfb) x9e6M'' – jessi

+0

我以为他们看起来很熟悉@MartijnPieters。这是发生了什么。 'conn.info()。headers ['Date:Fri,2013年5月31日14:13:01 GMT \ r \ n', '服务器:Apache/2.2.14(Ubuntu)\ r \ n', 'X -Powered-By:PHP/5.3.2-1ubuntu4.18 \ r \ n', '内容编码:gzip \ r \ n', '内容长度:645 \ r \ n', '连接:关闭\ r \ n', 'Content-Type:text/xml \ r \ n']'所以,它绝对看起来像gzip – jessi

+1

@Jessi:很难说没有测试,但在我看来,服务器坏了并会一直发送gzip。你必须解压缩它。 http://stackoverflow.com/questions/3947120/does-python-urllib2-will-automaticly-uncompress-gzip-data-from-fetch-webpage(甚至更好,因为Martijn建议,使用请求)。 –

相关问题