4.0 KiB
用 Python 下载加密和压缩文件
今年早些时候,我负责创建一个应用程序,使用 Python 从我们组织的网站下载信息。棘手的部分是,它将被加密、压缩,有效载荷将是 JSON。Python 能做到这一切吗?这正是我想知道的。现在是时候让你知道我的发现了。
Python 和加密
当务之急是找出加密的东西。有效载荷应该是 AES 加密的。虽然 Python 似乎没有为这类事情内置的模块,但有一个用于 Python 2.x 的优秀的 PyCrypto 包,运行得很好。不幸的是,他们的主网站没有列出如何在 Windows 上安装它。你需要自己做一些编译工作(我想是用 Visual Studio),或者你可以在这里下载迈克尔·福德的版本。我选择了后者。
以下是我最终使用的基本代码:
from Crypto.Cipher import AES
cipher = AES.new(key, AES.MODE_ECB)
gzipData = cipher.decrypt(encData).strip('\000')
encData 变量就是使用 urllib2 下载的文件。我们很快就会看到如何做到这一点。耐心点。密钥是由我的一个开发伙伴提供的。无论如何,一旦你解密了它,你就得到 gzipped 数据了。
解压缩 Gzipped 文件
关于 gzipped 的文档相当混乱。你用 gzip 还是 zlib?我花了不少时间反复试验才弄明白,主要是因为我的同事给了我错误的文件格式。这一部分实际上也非常容易完成:
import zlib
jsonTxt = zlib.decompress(gzipData)
如果你这样做了,你将得到解压缩的数据。是的,就是这么简单。
JSON 和 Python
从 Python 2.6 开始,Python 中提供了一个 json 模块。你可以在这里阅读。如果你坚持使用旧版本,那么你可以从 PyPI 下载这个模块。或者你可以使用 simplejson 包,我用的就是这个包。
import simplejson
json = simplejson.loads(jsonTxt )
现在,您将拥有一个嵌套字典列表。基本上,你会想做这样的事情来使用它:
data = json['keyName']
这将返回另一个包含不同数据的字典。您需要稍微研究一下数据结构,以找出访问所需内容的最佳方式。
把所有的放在一起
现在,让我们将它们放在一起,并向您展示完整的脚本:
import simplejson
import urllib2
import zlib
from Crypto.Cipher import AES
from platform import node
from win32api import GetUserName
version = "1.0.4"
uid = GetUserName().upper()
machine = node()
#----------------------------------------------------------------------
def getData(url, key):
"""
Downloads and decrypts gzipped data and returns a JSON string
"""
try:
headers = {"X-ActiveCalls-Version":version,
"X-ActiveCalls-User-Windows-user-ID":uid,
"X-ActiveCalls-Client-Machine-Name":machine}
request = urllib2.Request(url, headers=headers)
f = urllib2.urlopen(request)
encData = f.read()
cipher = AES.new(key, AES.MODE_ECB)
gzipData = cipher.decrypt(encData).strip('\000')
jsonTxt = zlib.decompress(gzipData)
return jsonTxt
except:
msg = "Error: Program unable to contact update server. Please check configuration URL"
print msg
if __name__ == "__main__":
json = getData("some url", "some AES key")
在这个特定的例子中,我还需要让服务器知道哪个版本的应用程序正在请求数据,用户是谁,以及请求来自哪台机器。为此,我们使用 urllib2 的 Request 方法向服务器传递一个包含该信息的特殊头。代码的其余部分应该是不言自明的
包扎
我希望这些都有意义,并且对您的 Python 冒险有所帮助。如果没有,请查看我在各个部分提供的链接,并做一点研究。玩得开心!