缘由

因为11月份是快递量比较大时候,会有有很多快递单需要查询快递状态;之前是因为单量少,每一个单每一个单去baidu 直接看百度查询到的结果。这两个月由于快递单特别多,于是就打算用Python 结合快递100的API 来查询快递状态

代码

快递100 API

实时查询状态

# coding = utf-8
import hashlib
import json

import requests


class KuaiDi100:
    def __init__(self):
        self.key = ''  # TODO 客户授权key
        self.customer = ''  # TODO 查询公司编号
        self.url = 'https://poll.kuaidi100.com/poll/query.do'  # 请求地址

    def track(self, com, num, phone, ship_from, ship_to):
        """
        物流轨迹实时查询
        :param com: 查询的快递公司的编码,一律用小写字母
        :param num: 查询的快递单号,单号的最大长度是32个字符
        :param phone: 收件人或寄件人的手机号或固话(也可以填写后四位,如果是固话,请不要上传分机号)
        :param ship_from: 出发地城市,省-市-区,非必填,填了有助于提升签收状态的判断的准确率,请尽量提供
        :param ship_to: 目的地城市,省-市-区,非必填,填了有助于提升签收状态的判断的准确率,且到达目的地后会加大监控频率,请尽量提供
        :return: requests.Response.text
        """
        param = {
            'com': com,
            'num': num,
            'phone': phone,
            'from': ship_from,
            'to': ship_to,
            'resultv2': '1',  # 添加此字段表示开通行政区域解析功能。0:关闭(默认),1:开通行政区域解析功能,2:开通行政解析功能并且返回出发、目的及当前城市信息
            'show': '0',  # 返回数据格式。0:json(默认),1:xml,2:html,3:text
            'order': 'desc'  # 返回结果排序方式。desc:降序(默认),asc:升序
        }
        param_str = json.dumps(param)  # 转json字符串

        # 签名加密, 用于验证身份, 按param + key + customer 的顺序进行MD5加密(注意加密后字符串要转大写), 不需要“+”号
        temp_sign = param_str + self.key + self.customer
        md = hashlib.md5()
        md.update(temp_sign.encode())
        sign = md.hexdigest().upper()
        request_data = {'customer': self.customer, 'param': param_str, 'sign': sign}
        return requests.post(self.url, request_data).text  # 发送请求


result = KuaiDi100().track('yuantong', 'YT9693083639795', '', '广东省江门市', '广东省深圳市')
print(result)

接口文档

https://api.kuaidi100.com/document/5f0ffb5ebc8da837cbd8aefc

导入快递单和填写结果

# coding = utf-8
import openpyxl
from openpyxl import Workbook
from kuaidi1000_function import KuaiDi100
import json
import time

wb = Workbook()
ws = wb.active

# 定义表头
title = ['客户名称','快递单号','快递状态','最后更新时间','快递开始时间','详情','时效/天']
ws.append(title)

start_time = time.time()

#读取excel表格
customer_file_path = 'F:/EXCEL/info/Customer.xlsx'
customer_workbook = openpyxl.load_workbook(customer_file_path)

# 获取工作表的Sheet
customer_sheet = customer_workbook['海运SEA']
sheet = customer_sheet.title

#顺丰快递需要手机号验证
air = 2699
sea = 8166
phone = ''

#判断当前表格是否海运还是空运并赋值给phone
if sheet == '海运SEA':
    phone = sea
else:
    phone = air


# 获取Customer.xlsx中A2:A100列的所有客户名字和B2:B100列的相对应的快递单号
customer_names =[(customer_sheet.cell(row=i, column=1).value) for i in range(2,100)]
express_numbers = [(customer_sheet.cell(row=i, column=2).value) for i in range(2,100)]



# 将快递单号使用for循环查询快递状态 ,并append 到 infomation_first中
for express_number, customer_name in zip(express_numbers,customer_names):
        
         response = KuaiDi100().track('',express_number,phone,'','')
         #定义获取到的数据
         api_data = json.loads(response)

         #判断数据是否存在
         if 'data' in api_data and api_data['data']:
             last_data = api_data['data'][-1] #取最末尾的数据
             first_data = api_data['data'][0] #取最前面的数据
             #imfromation_last = []   最末尾的数据[]
             infomation_first = [customer_name,express_number,
                                 first_data['status'],
                                 first_data['time'],
                                 last_data['time'],
                                 first_data['context']
                             ]
             ws.append(infomation_first)
         else:
            break
       
#在G栏 填入Excel 函数来计算时效 天数为单位
for row in range(2,ws.max_row + 1):
       formula = f'=DATEDIF(E{row},D{row},"D")'
       ws[f'G{row}'] = formula

# #格式化日期和时间
formatted_time = time.strftime("%H_%M_%S", time.localtime(time.time()))
formatted_date = time.strftime("%Y_%m_%d", time.localtime(time.time()))

#定义 文件路径和文件名
output_path = 'F:/EXCEL/output/快递更新状态'+formatted_date+"_"+formatted_time+'.xlsx'

#保存文件
wb.save(output_path)

end_time = time.time()
total_time = end_time - start_time

print(f"执行程序所花时间为: {total_time}")

print('=====Done====')

结果演示