工作需要写一个程序调用菜鸟物流云五级地址查询api,此处决定用python实现。
调用实例如图:
接口文档:
先申请获得appkey与resourceid:
需要查询的数据集:
读取文件存入一个list:
1 def get_address():
2 try:
3 with open(os.getcwd() + r'\address.txt', 'r') as f:
4 address = f.readlines()
5 return address
6 except:
7 print('打开文件失败')
8 return ''
构造请求参数:
1 def get_raw_input(address):
2 raw_input = {
3 "address": address,
4 "limit": "20"
5 }
6 return raw_input
构造公共请求参数:
1 def get_param(sign, content):
2 param = {
3 'msg_type': 'CNDZK_ADDRESS_QUERY',
4 'data_digest': sign,
5 'logistic_provider_id': 'd0119848ab......e1df5d8d6dc149',
6 'logistics_interface': content
7 }
8 return param
计算请求签名(MD5值算法与base64编码):
1 def get_data_digest(inputs, keys):
2 m1 = hashlib.md5()
3 m1.update((inputs + keys).encode('utf-8'))
4
5 # base64.b64encode(m1.hexdigest()) 得到错误值!!!
6 return base64.b64encode(m1.digest())
此处踩到几个坑卡了很久,主要是m1.hexdigest()与m1.digest()的不同,导致计算出的结果与java,js算出的不同
一开始以为是str转bytes的问题,注意python的str.encode('utf-8')与java的getBytes()结果在显示上有所不同(前者返回bytes类型,后者返回byte[]类型)
请求调用api并写入文件:
1 address_list = get_address()
2
3 for x in address_list:
4 # unicode形态转中文,去掉空格(否则查不出)
5 inputs = json.dumps(get_raw_input(x)).encode('utf-8').decode('unicode_escape').replace(' ', '')
6
7 result = requests.post(url, data=get_param(get_data_digest(inputs, keys), inputs), headers=headers)
8 result = result.content.decode(encoding='utf-8')
9 # print(result)
10 results = results + result + '\r\n'
11
12
13 try:
14 with open(os.getcwd()+r'\result.txt', 'w') as f:
15 f.write(results)
16 print("写入成功")
17 except:
18 print("写文件失败")
此处又踩到一个小坑-。-,由于python3.x的str类型中文数据默认采用unicode编码显示,所以会得到中文变成\u...的数据,导致查询失败
json.dumps()将dict转化为json字符串返回,先utf-8编码为bytes类型
再用decode('unicode_escape')解码让中文字符正常显示
同时请求参数中有空格也会导致查询失败(阿里api文档太简单什么都没说,参数只能自己慢慢调,差评)
所以此处用replace(' ','')除去空格
得到结果集:
完整代码:
1 # coding:utf-8
2 # by NeilShi 11/29/2017
3 import requests
4 import hashlib
5 import base64
6 import json
7 import os
8
9
10 # 'appkey': '154430',
11 # 'AppSecret': 'S7ib51Kp5......Qd10Lt4490QTwpr',
12 # 资源:d0119848ab5......df5d8d6dc149
13
14 url = 'http://link.cainiao.com/gateway/link.do'
15 keys = 'S7ib51Kp5O......d10Lt4490QTwpr'
16
17 headers = {
18 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
19 }
20
21 results = '' # 存放结果集
22
23
24 def get_address():
25 try:
26 with open(os.getcwd() + r'\address.txt', 'r') as f:
27 address = f.readlines()
28 return address
29 except:
30 print('打开文件失败')
31 return ''
32
33
34 def get_raw_input(address):
35 raw_input = {
36 "address": address,
37 "limit": "20"
38 }
39 return raw_input
40
41
42 def get_param(sign, content):
43 param = {
44 'msg_type': 'CNDZK_ADDRESS_QUERY',
45 'data_digest': sign,
46 'logistic_provider_id': 'd011984......d7ae1df5d8d6dc149',
47 'logistics_interface': content
48 }
49 return param
50
51
52 def get_data_digest(inputs, keys):
53 m1 = hashlib.md5()
54 m1.update((inputs + keys).encode('utf-8'))
55
56 # base64.b64encode(m1.hexdigest()) 得到错误值!!!原因未知
57 return base64.b64encode(m