工作需要寫一個程序調用菜鳥物流雲五級地址查詢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(m1.digest()) 58 59 60 address_list = get_address() 61 62 for x in address_list: 63 # unicode形態轉中文,去掉空格(否則查不出) 64 inputs = json.dumps(get_raw_input(x)).encode('utf-8').decode('unicode_escape').replace(' ', '') 65 66 result = requests.post(url, data=get_param(get_data_digest(inputs, keys), inputs), headers=headers) 67 result = result.content.decode(encoding='utf-8') 68 # print(result) 69 results = results + result + '\r\n' 70 71 72 try: 73 with open(os.getcwd()+r'\result.txt', 'w') as f: 74 f.write(results) 75 print("寫入成功") 76 except: 77 print("寫文件失敗")