ems

news2024/9/20 14:52:08

【python爬虫】邮政包裹物流查询

  • 目标网站 ems 邮政快递包裹查询:

https://www.ems.com.cn/

  • 截图

image-20230801214420758

  • 接口预览 image-20230801215145340

    • getPic请求滑动验证码的背景图片和滑块图片,返回的是base64编码的图片

    • getLogisticsTestFlag发送验证码的验证信息

      image-20230801215455640

      • xpos为滑动的距离,本站没有验证轨迹一说,属于验证码简单的一类
      • waybillNoList为需要查询的单号
    • queryTrack为查询物流的api

    • 请求头的加密参数

      image-20230801215918222

      • tickettime必须校验
      • user-sign没有校验
  • 解决思路

    • 滑动验证码采取ddddocr识别
    • 逆向tickettime请求头参数即可
  • js调试

    image-20230801220459596

    • 上图显示了这两个加密参数的加密逻辑

    • h()跟进去看是MD5

    • p.encode()base64

    • 需要注意的是querytrack那个接口的l参数不一样,如下

      image-20230801220725904

    • 另外,请求前需要获取一个服务器时间,穿插在每次请求前,这个是为了让获取的信息更加实时

  • 代码实现

import requests
import base64
import ddddocr
import hashlib
import json
from loguru import logger
logger.info("技术交流qq群:{}",529528142)
det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
headers = {
    'authority': 'www.ems.com.cn',
    'accept': 'application/json, text/plain, */*',
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
    # 'content-length': '0',
    'origin': 'https://www.ems.com.cn',
    'referer': 'https://www.ems.com.cn/',
    'sec-ch-ua': '"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-origin',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
}


def query_time():
    response = requests.post('https://www.ems.com.cn/ems-web/currentTime/queryTime', headers=headers)
    return response.json()["value"]


def getPic():
    response = requests.post('https://www.ems.com.cn/ems-web/cutPic/getPic', headers=headers).json()
    return response["value"]["capcode"], response["value"]["backImage"], response["value"]["slidingImage"], \
        response["value"]["yHeight"]


def verify(_ticket, _time, _xpos, _capcode):
    __headers = {
        'authority': 'www.ems.com.cn',
        'accept': 'application/json, text/plain, */*',
        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'content-type': 'application/json;charset=UTF-8',
        'origin': 'https://www.ems.com.cn',
        'referer': 'https://www.ems.com.cn/',
        'sec-ch-ua': '"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'ticket': _ticket,
        'time': _time,
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
    }

    json_data = {
        'value': {
            'customerIP': '你的ip',
            'phoneNum': '',
            'waybillNoList': [
                consult_code,
            ],
            'xpos': _xpos,
            'capcode': _capcode,
        },
    }
    response = requests.post('https://www.ems.com.cn/ems-web/trackTestQuery/getLogisticsTestFlag', headers=__headers,
                             json=json_data)
    # print(response.json())
    if response.json()["success"]:
        logger.info("验证成功")
    else:
        logger.error("验证失败")


def ddocr_get_pos(_slide, _bg):
    _slide_bytes = base64.b64decode(_slide)
    _bg_bytes = base64.b64decode(_bg)

    with open('./slide.png', 'wb') as f:
        f.write(_slide_bytes)

    with open('./bg.jpg', 'wb') as f:
        f.write(_bg_bytes)

    _res = det.slide_match(_slide_bytes, _bg_bytes)
    return _res


def get_ticket_(_time, _capcode, _type):
    o = _time
    n = o[0:3]
    r = o[3:]
    l = ""
    if _type == "verify":
        l = "1163FA15CC9A425EA4B65B2A218FF5F8"
    elif _type == "track":
        l = "053B245CB1B74EBBB5FBB4A5889D66B8"
    else:
        pass
    c = _capcode
    u = consult_code + n + l + r + c
    g = hashlib.md5(u.encode('utf-8')).hexdigest().upper()
    d = hashlib.md5(g.encode('utf-8')).hexdigest().upper()
    m = base64.b64encode(d.encode('utf-8')).decode('utf-8')
    return m


def query_track(_ticket, _time, _xpos, _capcode):
    headers_ = {
        'authority': 'www.ems.com.cn',
        'accept': 'application/json, text/plain, */*',
        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'content-type': 'application/json;charset=UTF-8',
        'origin': 'https://www.ems.com.cn',
        'referer': 'https://www.ems.com.cn/',
        'sec-ch-ua': '"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'ticket': _ticket,
        'time': _time,
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
    }

    json_data = {
        'value': [
            {
                'ip': '你的ip',
                'xpos': _xpos,
                'capcode': _capcode,
                'mailStatus': 'a',
                'orderNum': [
                    consult_code,
                ],
                'orderType': '1',
                'noRulesNum': [],
                'appleFlag': None,
            },
        ],
        'list': [
            consult_code,
        ],
    }

    response = requests.post('https://www.ems.com.cn/ems-web/mailTrack/queryTrack', headers=headers_, json=json_data)
    return response.json()


if __name__ == "__main__":
    consult_code = "12121212121"
    capCode, bg, slide, yheight = getPic()
    time_ = query_time()
    xpos_ = ddocr_get_pos(slide, bg)['target'][0] - 3
    logger.info("ddddocr->{}", xpos_)
    ticket_ = get_ticket_(_time=str(time_), _capcode=capCode, _type="verify")
    verify(_ticket=ticket_, _time=str(time_), _xpos=xpos_, _capcode=capCode)
    time_ = query_time()
    ticket_ = get_ticket_(_time=str(time_), _capcode=capCode, _type="track")
    info = query_track(_ticket=ticket_, _time=str(time_), _xpos=xpos_, _capcode=capCode)
    logger.info(info)
  • 运行截图

image-20230801221156097

技术交流群:529528142

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/821997.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CUDA编译器环境配置篇

cuda教程目录 第一章 指针篇 第二章 CUDA原理篇 第三章 CUDA编译器环境配置篇 第四章 kernel函数基础篇 第五章 kernel索引(index)篇 第六章 kenel矩阵计算实战篇 第七章 kenel实战强化篇 第八章 CUDA内存应用与性能优化篇 第九章 CUDA原子(atomic)实战篇 第十章 CUDA流(strea…

CHI中的System Debug, Trace, and Monitoring

Data Source indication □ Read request的completer,可以在CompData, DataSepResp, SnpRespData, and SnpRespDataPtl response中的datasource域段中指定data的来源;即使响应中带有错误,该datasource也是有效的; □ 该域段也可复…

Flutter 之Bloc入门指南实现倒计时功能

Flutter Timer By Bloc 前言Stream.periodic实现倒计时定义Bloc状态定义Bloc事件定义Bloc组件定义View层参考资料前言 使用Bloc开发Flutter的项目,其项目结构都很简单明确,需要创建状态,创建事件,创建bloc,创建对应的View。flutter_timer项目来分析下Bloc的使用方法。 通…

逻辑回归变量系数可为负数吗?应该如何解释?

之前很多学员来问逻辑回归变量系数是否都应该为正数,如果出现负的变量系数该怎么办?是否需要重新建模?这些学员都是在网上搜索时,被错误信息误导。网上信息可以随意转载,且无人审核对错。我见过最多情况时很多文章正确…

软工导论知识框架(三)结构化的设计

一.传统软件工程方法学采用结构化设计技术(SD) 从工程管理角度结构化设计分两步: 概要设计: 将软件需求转化为数据结构和软件系统结构。详细设计:过程设计,通过对结构细化,得到软件详细数据结构…

dubbo-helloworld示例

1、工程架构 2、创建模块 &#xff08;1&#xff09;创建父工程,引入公共依赖 pom.xml依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></depende…

MultipartFile 获取文件名、文件前缀、文件后缀、文件类型

测试 debug 方法 RequestMapping(value "/test",method RequestMethod.POST)public void fileUpload(MultipartFile file){// 文件名String originalFilename file.getOriginalFilename();// 文件名前缀String fileName file.getOriginalFilename().substring(0,…

第5讲:VBA中OFFSET函数的利用

【分享成果&#xff0c;随喜正能量】幸福从来不是跟别人比来的&#xff0c;追求不同&#xff0c;各有活法&#xff0c;开心了就笑&#xff0c;累了就休息&#xff0c;日子安稳踏实就是最大的幸福。做人就怕尊严扫地&#xff0c;保留一点做人的尊严&#xff0c;是人生最大的本钱…

C语言每日一题

今天分享的是一道牛客网上面的题目&#xff0c;链接在下面 有序序列合并 这道题做法有很多&#xff0c;最简单的是合并一起&#xff0c;然后用排序就行了&#xff0c;今天将一个最高效的办法&#xff0c;思路是两个数组第一项进行比较&#xff0c;小的先输出&#xff0c;输出的…

Mac上命令

1. block端口&#xff1a; sudo cp /etc/pf.conf /etc/pf443.conf 编辑pf443.conf&#xff0c;vim /etc/pf443.conf&#xff0c;如 block on en0 proto udp from any to any port 9000 # block UDP port 9000 block on en0 proto tcp from any to any port 5004 # bloc…

InnoDB引擎底层逻辑讲解——后台线程

1.后台线程 后台线程的作用就是将innodb存储引擎缓冲池中的数据&#xff0c;在合适的时机刷新到磁盘文件当中。innodb存储引擎后台的线程主要分为四类&#xff1a;

Golang之路---02 基础语法——函数

函数 函数定义 func function_name( [parameter list] ) [return_types] {函数体 }参数解释&#xff1a; func&#xff1a;函数由 func 开始声明function_name&#xff1a;函数名称&#xff0c;函数名和参数列表一起构成了函数签名。[parameter list]&#xff1a;参数列表&a…

Istio 安全 mTLS认证 PeerAuthentication

这里定义了访问www.ck8s.com可以使用http也可以使用https访问&#xff0c;两种方式都可以访问。 那么是否可以强制使用mtls方式去访问&#xff1f; mTLS认证 PeerAuthentication PeerAuthentication的主要作用是别人在和网格里的pod进行通信的时候&#xff0c;是否要求mTLS mTL…

信息学奥赛一本通——1258:【例9.2】数字金字塔

文章目录 题目【题目描述】【输入】【输出】【输入样例】【输出样例】 AC代码 题目 【题目描述】 观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径&#xff0c;使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。 在上面…

web前端开发工程师岗位的主要职责八篇

web前端开发工程师岗位的主要职责1 职责&#xff1a; 1、负责web前端系统和功能的开发、调试和维护&#xff0c;前端技术框架和js等互动效果开发; 2、负责公司现有项目和新项目的前端修改调试和开发工作; 3、根据工作安排高效、高质地完成代码编写&#xff0c;确保符合规范…

计算机视觉(六)图像分类

文章目录 常见的CNNAlexnet1乘1的卷积 VGG网络Googlenet&#xff08;Inception V1、V2、V3&#xff09;全局平均池化总结 Resnet、ResnextResNet残差网络ResNeXt网络 应用案例VGGResnet 常见的CNN Alexnet DNN深度学习革命的开始 沿着窗口进行归一化。 1乘1的卷积 VGG网络…

45.ubuntu Linux系统安装教程

目录 一、安装Vmware 二、Linux系统的安装 今天开始了新的学习&#xff0c;Linux,下面是今天学习的内容。 一、安装Vmware 这里是在 Vmware 虚拟机中安装 linux 系统&#xff0c;所以需要先安装 vmware 软件&#xff0c;然 后再安装 Linux 系统。 所需安装文件&#xff1a;…

Blueprint —— 蓝图通信

在使用蓝图时&#xff0c;如需在不同蓝图间传递或共享信息&#xff0c;此时就需要使用蓝图通信&#xff08;Blueprint Communication&#xff09;&#xff1b; 一&#xff0c;变量引用 创建变量&#xff0c;类型为指定对象的引用&#xff0c;默认值设置为指定对象的实例&#x…

多线程(JavaEE初阶系列7)

目录 前言&#xff1a; 1.常见的锁策略 1.1乐观锁和悲观锁 1.2轻量级锁和重量级锁 1.3自旋锁和挂起等待锁 1.4互斥锁与读写锁 1.5可重入锁与不可重入锁 1.6公平锁与非公平锁 2.CAS 2.1什么是CAS 2.2自旋锁的实现 2.3原子类 3.synchronized 3.1synchronized的原理以…

探秘二叉树后序遍历:从叶子到根的深度之旅

本篇博客会讲解力扣“145. 二叉树的后序遍历”的解题思路&#xff0c;这是题目链接。 本题的思路是&#xff1a; 先创建一个数组&#xff0c;用来存储二叉树后序遍历的结果。数组的大小跟树的结点个数有关。树的结点个数可以使用递归实现&#xff0c;即总个数左子树结点个数右…