数量接口发掘,物流查询
分类:计算机编程

前言

做超级市场项目标,最佳是能够一贯在百货集团中询问订单的物流音讯。所以新扩大物流查询成效。所用的物流查询,都由快递鸟提供。由于每一天查询的次数不可预感,所以需求将查询的数量寄放至数据库,防止再次查询,占用财富。

各队接口

澳门新葡8455手机版,微信徒人号机器人项目演习,方今功能有:

这两天做的品种有个须要,要利用物流单号即时查询物流音信,从英特网获知,关于物流的第三方API还是广大的,而本身选择的是快递鸟,快递鸟是二个无需付费的第三方接口,Api整合全世界400余家物流快递接口,长久免费不限次,接口与快递公司多通道通讯,可用性达到99.9%以上,推送速度定制配置,保险接入方系统的安居。

立时查询

选拔情状:若从数据库查询不到物流消息时,则调用即时查询,将抽取到的数目增四月数据库。成效情状:物流查询作用未更新此前的订单。 每一日调用次数节制不超过3000次,API地址: 澳门新葡8455手机版 1

  • 伸手参数RequestData
    //OrderCode  订单编号--订单编号可以为空,不是必填
    private String OrderCode;
    //ShipperCode   快递公司编码
    private String ShipperCode;
    //LogisticCode  物流单号
    private String LogisticCode;
  • 即时查询情势,MD5加密和base64编码官方demo中有,所以不再另行贴
    //请求url
    private static final String ReqURL="http://api.kdniao.cc/Ebusiness/EbusinessOrderHandle.aspx";

    /**
     * 即时查询
     * @param ShipperCode  快递公司编码
     * @param LogisticCode 物流运单号
     * @throws Exception
     */
    public static String TrackQuery(String ShipperCode, String LogisticCode) throws Exception {
        TrackQueryRequestData trackQueryRequestData = new TrackQueryRequestData();
        trackQueryRequestData.setShipperCode(ShipperCode);
        trackQueryRequestData.setLogisticCode(LogisticCode);
        String requestData = JSONObject.fromObject(trackQueryRequestData).toString();
        Map<String, String> params = new HashMap<String, String>();
        params.put("RequestData", urlEncoder(requestData, "UTF-8"));
        params.put("EBusinessID", Commons.getKDNEBusinessID());
        params.put("RequestType", "1002");
        String dataSign = encrypt(requestData, Commons.getKDNAppKey(), "UTF-8");
        params.put("DataSign", urlEncoder(dataSign, "UTF-8"));
        params.put("DataType", "2");

        String result = sendPost(ReqURL, params);

        return result;
    }

    快递查询API有即时查询和订阅查询二种,即时是伸手即重返数据,订阅则是订阅快递单号到接口,有物流轨迹更新则全量重临数据。近来常用的有快递鸟、快递100、快递网等。

  • 四六级
  • 快递
  • 天气
  • 电影票房
  • 通识课标题

使用进程

物流查询

动用情形:没新扩充二个订单,发货时去订阅物流消息,并将快递集团编码和快递单号存放至数据库,当物流新闻更新之后,接到快递鸟推送过来的新闻,再将消息update至数据库。 适用于日查询量>3000次的网址和种类,恳求参数同即时查询。

  • 接口地址: API测量试验地点:
  • API正式地址: 物流查询分为多少个部分:订阅和推送。

    快递鸟即时API能够查询3000次,3000上述接订阅接口,统豆蔻梢头接口格局接入,常用特快专递均援协助调查询,还只怕有订阅API、在线下单API、电子面单API,接口均不选择资费,未有须求客户拉长外链,支持418家国内外快递物流查询。

网络的接口多数收取费用,无偿版本还亟需申请,于是去那个网址做了轻便的调整后,拿到了几个url 查询伪接口。

报到网址

订阅

依靠快递集团编码和快递单号,对物流新闻进行订阅,能够进来调剂平台开展调试,方法如下:

//请求url--正式
    private static final String ReqURL="http://api.kdniao.cc/api/dist";
    //请求url--测试
//    private static String ReqURL="http://testapi.kdniao.cc:8081/api/dist";

    /**
     * Json方式  物流追踪
     * @throws Exception
     */
    public static String SubscribeOrderTraces(String ShipperCode, String LogisticCode) throws Exception{
        SubscribeRequestData subscribeRequestData = new SubscribeRequestData();
        subscribeRequestData.setLogisticCode(LogisticCode);
        subscribeRequestData.setShipperCode(ShipperCode);
        String requestData = JSONObject.fromObject(subscribeRequestData).toString();
        Map<String, String> params = new HashMap<String, String>();
        params.put("RequestData", urlEncoder(requestData, "UTF-8"));
        params.put("EBusinessID", Commons.getKDNEBusinessID());
        params.put("RequestType", "1008");
        String dataSign=encrypt(requestData, Commons.getKDNAppKey(), "UTF-8");
        params.put("DataSign", urlEncoder(dataSign, "UTF-8"));
        params.put("DataType", "2");

        String result=sendPost(ReqURL, params);

        //根据公司业务处理返回的信息......

        return  result;
    }

订阅成功后,快递鸟会回来三个JSON数据,例如:

{
        "EBusinessID": "1151847",
        "UpdateTime": "2016-08-09 16:42:38",
        "Success": true,
        "Reason": ""
        }

success重返true,则代表订阅成功。

    快递100天天能够防费查询贰零零壹遍,超过贰零零贰回收取金钱,每回0.06~0.1元不等,假如查询的量大的话能够减低资费,无需付费的接口有几家常用快递不扶助接口格局,只补助htmlAPI,供给客户拉长外链,辅助300多家国内外快递物流查询。

接受到的库:

作用
urllib quote 方法对中文编码
requests 仿浏览器发起请求
Beautifulsoup 解析表单
json 处理服务器的 response 数据

因为小编意气风发旦用的是即时查询,所以报名的便是即时查询的api。

推送

订阅成功后,当物流音信有立异的时候,快递鸟会发送一条推送,必要三个借口去接收音讯,并将吸收接纳到的音信更新至数据库。方法如下:

/**
     * 物流推送
     *  接收快递鸟推送过来的消息,并将消息存放至数据库
     * @param request
     */
    @RequestMapping(value="subscribeExpress")
    @ResponseBody
    public String subscribeExpress(HttpServletRequest request){
        JSONObject object = JSONObject.fromObject(request.getParameter("RequestData"));
        ExpressDetail expressDetail;
        JSONArray data = object.getJSONArray("Data");
        if (!Commons.isNull(data) && data.size() > 0){
            for (int i = 0; i < data.size(); i  ) {
                JSONObject detail = data.getJSONObject(i);
                String shippercode = detail.getString("ShipperCode");
                String logisticcode = detail.getString("LogisticCode");
                ExpressDetail expressDetail1 = expressDetailService.selectByShipperAndLogistic(shippercode,logisticcode);
                if (Commons.isNull(expressDetail1)) {
                    expressDetail = new ExpressDetail();
                    expressDetail.setLogisticcode(logisticcode);
                    expressDetail.setShippercode(shippercode);
                    expressDetail.setEdittime(new Date());
                    if (detail.containsKey("State")){
                        expressDetail.setState(detail.getString("State"));
                    }else {
                        expressDetail.setState("4");
                    }
                    if (detail.getString("Traces") == null || "[]".equals(detail.getString("Traces"))){
                        expressDetail.setTracedetail("[{"error":"" detail.getString("Reason") ""}]");
                    } else {
                        expressDetail.setTracedetail(detail.getString("Traces"));
                    }
                    expressDetailService.insert(expressDetail);
                } else {
                    expressDetail = new ExpressDetail();
                    expressDetail.setId(expressDetail1.getId());
                    expressDetail.setEdittime(new Date());
                    expressDetail.setState(detail.getString("State"));
                    expressDetail.setTracedetail(detail.getString("Traces"));
                    expressDetailService.updateById(expressDetail);
                }
            }
        }
        JSONObject result = new JSONObject();
        result.put("EBusinessID", Commons.getKDNEBusinessID());
        result.put("UpdateTime", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
        result.put("Success", true);
        result.put("Reason","");
        return result.toString();
    }

注意:选取到推送之后,必要求回到一个多少,告诉快递鸟选择推送成功。假使传递至特快专递鸟的订单数量有误,则赶回的信息里面,也许未有state和traces的值,这时候再次回到值中,Reason应有原因,这种景色须要开展管理。

    特快专递网每一日能够无需付费查询500次,超过500次收取费用,每一遍0.05元,独有即时查询和订阅推送接口,要求客户增加外链,补助395家国内外特快专递物流查询。

1、四六级接口

四六级查询有多少个法定查询网站,中国引导考试网和中黄炎子孙民共和国高传授生新闻网(学信网),学信网的表明办法较为轻巧,反应一点也不慢,此番调节和测验选拔学信网。

调理进程:

  1. 构造 headers 包括 user-agentreferer(贫乏 referer 则查询失败)
  2. 亟待付出的表单有 zkzh(准考证号)、xm(姓名)
  3. 归来成功的数据选拔 Beautifulsoup 剖判相关音讯
import urllib
import requests
from bs4 import BeautifulSoup
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.3397.16 Safari/537.36',
    "Referer": "http://www.chsi.com.cn/cet/",
}
def get_grade(name, number):
    try:                 # 姓名和学号可以互换
        int(number)
    except Exception as e:
        # print(e)
        name,number = number,name
    name = urllib.quote(name)
    # 构造url相关信息,用get发起请求
    response = requests.get(
        "http://www.chsi.com.cn/cet/query?zkzh={}&xm={}".format(number, name),
        headers=headers, allow_redirects=False)
    # 对返回的页面进行解析
    soup = BeautifulSoup(response.text, "html.parser")
    infos = soup.select("table.cetTable td")
    message = u""
    message  = u"姓名:"   infos[0].get_text().strip()   "n"
    message  = u"学校:"   infos[1].get_text().strip()   "n"
    message  = u"考试级别:"   infos[2].get_text().strip()   "n"
    message  = u"准考证号:"   infos[3].get_text().strip()   "n"
    message  = u"笔试成绩"   "n"
    message  = u"总分:"   infos[4].get_text().strip()   "n"
    message  = u"听力:"   infos[6].get_text().strip()   "n"
    message  = u"阅读:"   infos[8].get_text().strip()   "n"
    message  = u"写作和翻译:"   infos[10].get_text().strip()   "n"
    message  = u"口试成绩"   "n"
    message  = u"准考证号:"   infos[11].get_text().strip()   "n"
    message  = u"等级:"   infos[12].get_text().strip()   "n"
    print(message)
    return message
get_grade("准考证号","姓名")

重回信息:

姓名:李四
学校:XX大学
考试级别:英语六级
准考证号:111111112222222
笔试成绩
总分:499
听力:222
阅读:150
写作和翻译:127
口试成绩
准考证号:--
等级:--

客商只要提供快递单号和快递公司

以下是代码

  • 数据库字段
    private Long id;
    private String orderid;
    private String shippercode;
    private String logisticcode;
    //物流状态:0-无轨迹,1-已揽收, 2-在途中 201-到达派件城市,3-签收,4-问题件
    private String state;
    private Date edittime;
    private String tracedetail;
  • 新订单发货
//发货时去订阅物流消息
                        String shippercode = GetShipperCode.getShipperCode(deliverOrder.getExpress());
                        String detail = ExpresseSubscribe.SubscribeOrderTraces(shippercode,deliverOrder.getExpressno());
                        JSONObject obj = JSONObject.fromObject(detail);
                        if (obj.containsValue("true")) {
                            //订阅消息之后,将相应数据存入数据库
                            ExpressDetail expressDetail = new ExpressDetail();
                            expressDetail.setOrderid(String.valueOf(orderid));
                            expressDetail.setShippercode(shippercode);
                            expressDetail.setLogisticcode(deliverOrder.getExpressno());
                            expressDetail.setEdittime(new Date());
                            expressDetail.setTracedetail("暂时没有物流信息。");
                            expressDetailService.insert(expressDetail);
                        }
  • 得到数据库数据
/**
     * 获取物流详情
     */
    @RequestMapping(value = "getExpresseDetail",method = RequestMethod.POST)
    @ResponseBody
    public Result getExpresseDetail(@RequestBody Long orderid,HttpServletRequest request){
        DeliverOrder deliverOrder = orderDao.queryDeliverOrderByOrderId(orderid);
        if (deliverOrder==null){
            return new Result(Result.Status.ERROR, "deliverOrder为空");
        }
        if (deliverOrder.getExpress()==null){
            return new Result(Result.Status.ERROR, "快递为空");
        }
        if (deliverOrder.getExpressno()==null){
            return new Result(Result.Status.ERROR, "快递编号为空");
        }
        String shippercode = GetShipperCode.getShipperCode(deliverOrder.getExpress());
        ExpressDetail detail = expressDetailService.selectByShipperAndLogistic(shippercode,deliverOrder.getExpressno());
        if (Commons.isNull(detail)) {
            try {
                String result = ExpresseTrack.TrackQuery(shippercode,deliverOrder.getExpressno());
                JSONObject objDetail = JSONObject.fromObject(result);
                ExpressDetail expressDetail = new ExpressDetail();
                expressDetail.setOrderid(String.valueOf(orderid));
                expressDetail.setShippercode(shippercode);
                expressDetail.setLogisticcode(deliverOrder.getExpressno());
                expressDetail.setEdittime(new Date());
                if (objDetail.containsKey("State")){
                    expressDetail.setState(objDetail.getString("State"));
                }
                if (objDetail.getString("Traces")==null||objDetail.getString("Traces")=="[]"){
                    expressDetail.setTracedetail(objDetail.getString("Reason"));
                }
                expressDetail.setTracedetail(objDetail.getString("Traces"));
                expressDetailService.insert(expressDetail);
                detail = expressDetailService.selectByShipperAndLogistic(shippercode,deliverOrder.getExpressno());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return new Result(Result.Status.OK,JSONObject.fromObject(detail));
    }
  • 透过快递公司编码和快递单号查询,订单号码是可选字段,如需求也可拉长订单号码
@Override
    public ExpressDetail selectByShipperAndLogistic(String shipperCode, String logisticCode) {
        ExpressDetail expressDetail = new ExpressDetail();
        expressDetail.setShippercode(shipperCode);
        expressDetail.setLogisticcode(logisticCode);
        ExpressDetail detail = expressDetailDao.selectOne(expressDetail);
        return detail;
    }
  • ctrl.js--ng的多寡处理
/**
         * 物流详情
         */
        scope.expresseDetail = function(){
            var id = routeParams.id;
            orderService.getExpresseDetail(id,function(data){
                if (data.status == 'OK'){
                    console.log(data.message);
                    scope.expressDetail = data.message;
                    scope.tracedetails = [];
                    var detail = JSON.parse(scope.expressDetail.tracedetail);
                    console.log(scope.expressDetail);
                    //某事件内物流详情
                    var tracedetail = {};
                    //用于存放某天内的所有物流信息
                    var traces = [];
                    //用于存放整个物流所需多少天
                    var traces1 = [];
                    var dateForDay = {};
                    for (var i = 0; i < detail.length; i  ){
                        var accepttime = detail[i].AcceptTime;
                        var time = accepttime.split(" ");
                        if (i == 0) {
                            dateForDay.date = time[0];
                            dateForDay.week = scope.getWeekName(new Date(time[0]).getDay());
                            tracedetail = {};
                            tracedetail.date = time[1];
                            tracedetail.detail = detail[i].AcceptStation;
                            traces1.push(tracedetail);
                        } else {
                            var upaccepttime = detail[i - 1].AcceptTime;
                            var uptime = upaccepttime.split(" ");
                            if (time[0] == uptime[0]) {
                                tracedetail = {};
                                tracedetail.date = time[1];
                                tracedetail.detail = detail[i].AcceptStation;
                                traces1.push(tracedetail);
                                if (i == detail.length -1) {
                                    dateForDay.traces = traces1;
                                    traces.push(dateForDay);
                                }
                            } else {
                                dateForDay.traces = traces1;
                                traces.push(dateForDay);
                                dateForDay = {};
                                dateForDay.date = time[0];
                                dateForDay.week = scope.getWeekName(new Date(time[0]).getDay());
                                traces1 = [];
                                tracedetail = {};
                                tracedetail.date = time[1];
                                tracedetail.detail = detail[i].AcceptStation;
                                traces1.push(tracedetail);
                                if (i == detail.length -1) {
                                    dateForDay.traces = traces1;
                                    traces.push(dateForDay);
                                }
                            }
                        }
                    }
                    scope.traces = traces;
                    console.log(scope.traces);
                }
            })
        };

        scope.getWeekName = function(index) {
            var result = "";
            switch (index){
                case 0:
                    result = "周日";
                    break;
                case 1:
                    result = "周一";
                    break;
                case 2:
                    result = "周二";
                    break;
                case 3:
                    result = "周三";
                    break;
                case 4:
                    result = "周四";
                    break;
                case 5:
                    result = "周五";
                    break;
                case 6:
                    result = "周六";
                    break;
            }
            return result;
        };
  • 陈设文件设置
  1. Commons.java
 public static String getKDNEBusinessID(){
        String EBusinessID = ConfigurationHolder.getInstance().getProperty("kuaidiniao.ebusinessid");
        return EBusinessID;
    }

    public static String getKDNAppKey(){
        String AppKey = ConfigurationHolder.getInstance().getProperty("kuaidiniao.appkey");
        return AppKey;
    }

2.application.properties,具体用****代替

#快递鸟
kuaidiniao.ebusinessid=********
kuaidiniao.appkey=*******************************
  1. spring-mvc.xml
<mvc:exclude-mapping path="/expressdetail/subscribeExpress"/>

4.applicationContext-cluster.xml

<property name="filterChainDefinitions">
            <value>
                 /expressdetail/subscribeExpress = anon
            </value>
        </property>

 

2、快递查询

接口来源,快递 100 。

疗养进程:

  1. 通过快递单号获取到特快专递公司名称,再次来到 json 格式的数额
  2. 用 json 库剖析数据,筛选集团名称
  3. 再将快递单号公司名称用 get 方法拿到快递消息
import requests
import json
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.3397.16 Safari/537.36',
}
def get_company(number): # 根据单号获取快递公司名称
    response = requests.get("http://www.kuaidi100.com/autonumber/autoComNum?resultv2=1&text={}".format(str(number)),
                            headers=headers, )
    result = json.loads(response.text)
    company_result = result["auto"][0]["comCode"]
    return company_result, number


def get_state(number):  # 查询快递状态
    args = get_company(number)
    response = requests.get("http://www.kuaidi100.com/query?type={}&postid={}".format(args[0], args[1]),
                            headers=headers)
    result = json.loads(response.text)
    print(result)
    message = ""
    for info in result["data"]:
        message  = info.get("ftime", "")   info.get("context", "")   "n"
    print(message)
    return message

get_state("71182629191986")

重回信息:

·······
2017-10-14 21:00:56宁波市|发件|宁波市【宁波转运中心】,正发往【金华转运中心】
2017-10-14 20:00:12宁波市|到件|到宁波市【宁波转运中心】
2017-10-14 13:43:55宁波市|收件|宁波市【宁波北仑】,【菜鸟上善/86103085】已揽收

通过api得到物流状态,并把结果回到

最后

广大雷同的从头到尾的经过就从不任何放上来。项目中存在拦截,所以布署文件中要做相应的拍卖。以上既是具备。

 

3、电影票房查询

各大门户都有连锁的电影票房信息,在此选用调节和测量检验华夏票房 。

调整进度:

  1. 将近来时光发送至相关 url ,重返 json 格式数据
  2. 深入分析 json 数据就能够
import requests
import json
import time

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.3397.16 Safari/537.36',
}


def get_movie():
    now_time = str(int(time.time()*1000))
    response = requests.get("http://www.cbooo.cn/BoxOffice/GetHourBoxOffice?d={}".format(now_time), headers=headers)
    data = json.loads(response.text)
    sum_box = u"今日总票房:"   data["data1"][0].get("sumBoxOffice", "")   u"万 "   u" (每五分钟更新)n"
    form = ""
    for movie_detail in data["data2"][0:10]:
        form  = movie_detail["Irank"]   u"、"   movie_detail["MovieName"]   " "
        form  = u"实时票房:"   movie_detail["BoxOffice"]   u"万 "
        form  = u"票房占比:"   movie_detail["boxPer"]   u"% "
        form  = u"上映天数:"   movie_detail["movieDay"]   u"天 "
        form  = u"累计票房:"   movie_detail["BoxOffice"]   u"万 "
        form  = u"实时票房:"   movie_detail["sumBoxOffice"]   u"万n"
    print(sum_box   form)
    return sum_box   form


get_movie()

前 10 位票房音信:

今日总票房:1181.8万  (每五分钟更新)
1、王牌特工2:黄金圈 实时票房:340.92万 票房占比:28.85% 上映天数:7天 累计票房:340.92万 实时票房:34148.57万
2、常在你左右 实时票房:235.56万 票房占比:19.93% 上映天数:0天 累计票房:235.56万 实时票房:252.06万
3、羞羞的铁拳 实时票房:142.22万 票房占比:12.03% 上映天数:27天 累计票房:142.22万 实时票房:207534.35万
····

我们获得结果,实行实时管理展现。

对接示例

4、天气查询

来源:心知天气api,官方网址注册后可拿到部分无需付费天气调用次数。

调度进程:

  1. 昨今区别的天气新闻有差异的 api
  2. 官方有相关 demo
import requests
import json
from pypinyin import lazy_pinyin

KEY = 'your api'  # API key
UID = "your id"  # 用户ID
Daily_API = 'https://api.seniverse.com/v3/weather/daily.json'  # API URL,可替换为其他 URL
UNIT = 'c'  # 单位
LANGUAGE = 'zh-Hans'  # 查询结果的返回语言

def fetchWeather(location):
    daily_result = requests.get(Daily_API, params={
        'key': KEY,
        'location': location,
        'language': LANGUAGE,
        'unit': UNIT
    })
    return daily_result.text


def get_Weather(city):
    message = ""
    all_result = fetchWeather(city)
    suggestion = json.loads(all_result[0])
    daily = json.loads(all_result[1])
    message  = u"地点:"   daily["results"][0]["location"]["name"]   "n"
    message  = u"日期:"   daily["results"][0]["daily"][0]["date"]   "n"
    message  = u"白天天气:"   daily["results"][0]["daily"][0]["text_day"]   "n"
    # ····
    print(message)
    return message

get_Weather("shanghai") # 上海的拼音,相关拼音转换可搜索相关库

回到新闻:

地点:上海
日期:2017-10-26
白天天气:阴
···

API参数

    以快递鸟及时查询API接入示例,分歧厂家的特快专递查询API接入近似,都急需注册,申请账号获得KEY和ID,若是是订阅API须求手艺联调。

5、通识课查询

来源于试检验资金料网。

调节进程:

  1. 该网址对将要查询难点用 js 举行加密
  2. 查询成功后,答案也开展了连带加密
  3. 分一次访谈,第叁次倡议服务器拿到标题url,第叁遍呼吁标题url获取答案
  4. 询问生龙活虎道难点要求探望两回该网址,有一些耗费时间
import re
import requests
import urllib
from bs4 import BeautifulSoup
import json
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.3397.16 Safari/537.36',
}
def utf8_decode(utf_text):  # 对题目进行加密,查看js代码写出python版 
    string1 = ""
    i1 = 0
    while i1 < len(utf_text):
        c = ord(utf_text[i1])
        if c < 128:
            string1  = chr(c)
            i1 = i1   1
        elif 191 < c < 224:
            c2 = ord(utf_text[i1   1])
            string1  = chr(((c & 31) << 6) | (c2 & 63))
            i1 = i1   2
        else:
            c2 = ord(utf_text[i1   1])
            c3 = ord(utf_text[i1   2])
            string1  = chr(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63))
            i1 = i1   3
    # print(string1)
    return string1


def decode_result(encoded_text): # 对返回的答案进行解密,查看js代码写出python版
    text = encoded_text
    _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 /="
    i = 0
    output1 = ""
    input1 = re.sub(r'[^A-Za-z0-9 /=]', "", text, re.S)
    while i < len(input1):
        enc1 = _keyStr.index(input1[i])
        i = i   1
        enc2 = _keyStr.index(input1[i])
        i = i   1
        enc3 = _keyStr.index(input1[i])
        i = i   1
        enc4 = _keyStr.index(input1[i])
        i = i   1
        chr1 = (enc1 << 2) | (enc2 >> 4)
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2)
        chr3 = ((enc3 & 3) << 6) | enc4
        output1 = output1   chr(chr1)
        if enc3 != 64:
            output1 = output1   chr(chr2)
        if enc4 != 64:
            output1 = output1   chr(chr3)

    output1 = utf8_decode(output1)
    if "tiku/shiti" in output1:
        number = re.match(r".*?(d ).*", output1)
        return number.group(1)
    else:
        raise Exception("无法查询此题目")

def get_question(question):  # 题目编码后向服务器获取题目答案地址,地址在返回的 json 中
    trans = urllib.parse.quote(question.encode("gb2312"))
    url = "https://data.api.ppkao.com/Interface/UserQueryApi.ashx?action=GetUserQueryWord&word={}&page=1".format(trans)
    response = requests.get(url, headers=headers)
    text = json.loads(response.text[13:-1])
    link_code = text["UserQueryList"][0].get("urlPC", "")
    if link_code is "":
        link_code = text["UserQueryList"][0].get("urlApp", "")
    return link_code

def get_answer(id):  # 最后解析题目答案
    url = "http://user.ppkao.com/mnkc/tiku/?id={}".format(id)
    response = requests.get(url, headers)
    soup = BeautifulSoup(response.text, "lxml")
    obj = re.search(r".*查看答案!(.*)进入题库.*", soup.text, re.S)
    # print(obj.group(1).strip())
    bb = ""
    for aw in obj.group(1).strip().split("n"):
        if aw:
            bb  = aw   "n"
    print(bb)
    # print(obj.group(1).strip())
    return bb

def final_get_answer(question):
    abc = get_question(question)
    defg = decode_result(abc)
    return get_answer(defg)

final_get_answer("冥王星与其他大行星迥异的特点不包括")

回来答案:

单项选择题
冥王星与其他大行星迥异的特点不包括()。

    A、公转轨道平面偏角较大
    B、未清空轨道附近其他天体
    C、体积比一些卫星还小
    D、太阳位于其轨道的一个焦点上
参考答案:D

地点那些都是合法给出的关于API的参数,不过大家得以看官方的demo实行摸底。官方的demo也是粗略易懂的。大家能够把它再也卷入。

    根据特快专递单号和快递公司编码查询物流轨迹消息。接口须求钦命快递单号的快递集团编码,格式不对或则编码错误都会返战败的新闻。如:EMS物流单号应慎选快递集团编码(EMS)查看快递公司编码重回的物流追踪新闻遵照产生的时光升序排列。

写在背后

在此四个职能中,较难的是通识课的调养,需求涉及到 js 代码、加解密等 ,别的多少个调养较为轻松,将 json 数据转成 python 的字典、用 requests 布局央求。

封装API

    接口帮衬的音讯选用格局为HTTP POST

接纳API供给八个定位参数

    伏乞方法的编码格式(utf-8卡塔尔(英语:State of Qatar):"application/x-www-form-urlencoded;charset=utf-8"

  1. 请求url,ReqURL

    API地址:

商贩id和API key都能够在快递鸟网址的本人的管住首页看见,而诉求url就是

 

 

/** * @param $ShipperCode 快递公司编号 * @param $order_sn 运单号 */public function getMessage($ShipperCode,$order_sn){ $requestData= "{'OrderCode':'','ShipperCode':'".$ShipperCode."','LogisticCode':'".$order_sn."'}"; $datas = array( 'EBusinessID' => self::EBusinessID, 'RequestType' => '1002',//接口指令1002,固定 'RequestData' => urlencode , 'DataType' => '2', //数据返回格式 2 json ); //把$requestData进行加密处理 $datas['DataSign'] = $this -> encrypt($requestData, self::AppKey); $result = $this -> sendPost( self::ReqURL, $datas); return $result;}

接口参数

那主方法中,传递步入的参数有五个,二个是快递公司编号,三个是物流订单号。

    *伸手系统级参数

作者们还供给把$requestData进行加密处理,也正是encrypt方法。

参数名称 类型 说明 必须要求
RequestData String 请求内容需进行URL(utf-8)编码。请求内容JSON或XML格式,须和DataType一致。 R
EBusinessID String 商户ID,请在我的服务页面查看。 R
RequestType String 请求指令类型:1002 R
DataSign String 数据内容签名:把(请求内容(未编码) AppKey)进行MD5加密,然后Base64编码,最后进行URL(utf-8)编码。详细过程请查看Demo。 R
DataType String 请求、返回数据类型:1-xml,2-json;默认为xml格式 O
/* * 进行加密 */function encrypt { return urlencode(base64_encode;}

   

加密然后就径直通过ReqUTiggoL进行寻访,重回的数据正是物流音信。

    *倡议内容字段定义

 self::EBusinessID, 'RequestType' => '1002',//接口指令1002,固定 'RequestData' => urlencode , 'DataType' => '2', //数据返回格式 2 json ); //把$requestData进行加密处理 $datas['DataSign'] = $this -> encrypt($requestData, self::AppKey); $result = $this -> sendPost( self::ReqURL, $datas); return $result; } /** * post提交数据 * @param string $url 请求Url * @param array $datas 提交的数据 * @return url响应返回的html */ function sendPost { $temps = array(); foreach ($datas as $key => $value) { $temps[] = sprintf('%s=%s', $key, $value); } $post_data = implode; $url_info = parse_url; if(empty { $url_info['port']=80; } $httpheader = "POST " . $url_info['path'] . " HTTP/1.0rn"; $httpheader.= "Host:" . $url_info['host'] . "rn"; $httpheader.= "Content-Type:application/x-www-form-urlencodedrn"; $httpheader.= "Content-Length:" . strlen . "rn"; $httpheader.= "Connection:closernrn"; $httpheader.= $post_data; $fd = fsockopen($url_info['host'], $url_info['port']); fwrite; $gets = ""; $headerFlag = true; while  { if () && ($header == "rn" || $header == "n")) { break; } } while  { $gets.= fread; } fclose; return $gets; } /* * 进行加密 */ function encrypt { return urlencode(base64_encode; }}$model = new KuaidiController();$res = $model -> getMessage;echo "";var_dump;
参数 类型 说明 必须要求
OrderCode String 订单编号 O
ShipperCode String 快递公司编码 R
LogisticCode String 物流单号 R

上述所述是笔者给我们介绍的PHP使用第三方即时收获物流动态,希望对我们享有利于,如若大家有别的疑问请给小编留言,笔者会及时还原我们的。在这里也特别感激我们对剧本之家网址的帮忙!

   

    *回去参数定义

参数名称

类型

说明

非得须要

EBusinessID

String

用户ID

R

OrderCode

String

订单号码

O

ShipperCode

String

快递集团编码

R

LogisticCode

String

物流运单号

R

Success

Bool

家成业就与否

R

Reason

String

破产原因

O

State

String

物流状态:2-在途中,3-签收,4-难题件

R

Traces

Trace

AcceptTime

String

时间

R

AcceptStation

String

描述

R

Remark

String

备注

O

 

 

JAVA接入示例

  1 import java.io.BufferedReader;
  2 import java.io.IOException;
  3 import java.io.InputStreamReader;
  4 import java.io.OutputStreamWriter;
  5 import java.io.UnsupportedEncodingException;
  6 import java.net.HttpURLConnection;
  7 import java.net.URL;
  8 import java.net.URLEncoder;
  9 import java.security.MessageDigest;
 10 import java.util.HashMap;
 11 import java.util.Map; 
 12 
 13 /**
 14  *
 15  * 快递鸟物流轨迹即时查询接口
 16  *
 17  * @技术QQ群: 456320272
 18  * @see: http://www.kdniao.com/YundanChaxunAPI.aspx
 19  * @copyright: 深圳市快金数据技术服务有限公司
 20  *
 21  * DEMO中的电商ID与私钥仅限测试使用,正式环境请单独注册账号
 22  * 单日超过500单查询量,建议接入我方物流轨迹订阅推送接口
 23  * 
 24  * ID和Key请到官网申请:http://www.kdniao.com/ServiceApply.aspx
 25  */
 26 
 27 public class KdniaoTrackQueryAPI {
 28     
 29     //DEMO
 30     public static void main(String[] args) {
 31         KdniaoTrackQueryAPI api = new KdniaoTrackQueryAPI();
 32         try {
 33             String result = api.getOrderTracesByJson("ANE", "210001633605");
 34             System.out.print(result);
 35             
 36         } catch (Exception e) {
 37             e.printStackTrace();
 38         }
 39     }
 40     
 41     //电商ID
 42     private String EBusinessID="请到快递鸟官网申请http://www.kdniao.com/ServiceApply.aspx";
 43     //电商加密私钥,快递鸟提供,注意保管,不要泄漏
 44     private String AppKey="请到快递鸟官网申请http://www.kdniao.com/ServiceApply.aspx";
 45     //请求url
 46     private String ReqURL="http://api.kdniao.cc/Ebusiness/EbusinessOrderHandle.aspx";    
 47  
 48     /**
 49      * Json方式 查询订单物流轨迹
 50      * @throws Exception 
 51      */
 52     public String getOrderTracesByJson(String expCode, String expNo) throws Exception{
 53         String requestData= "{'OrderCode':'','ShipperCode':'"   expCode   "','LogisticCode':'"   expNo   "'}";
 54         
 55         Map<String, String> params = new HashMap<String, String>();
 56         params.put("RequestData", urlEncoder(requestData, "UTF-8"));
 57         params.put("EBusinessID", EBusinessID);
 58         params.put("RequestType", "1002");
 59         String dataSign=encrypt(requestData, AppKey, "UTF-8");
 60         params.put("DataSign", urlEncoder(dataSign, "UTF-8"));
 61         params.put("DataType", "2");
 62         
 63         String result=sendPost(ReqURL, params);    
 64         
 65         //根据公司业务处理返回的信息......
 66         
 67         return result;
 68     }
 69     
 70     /**
 71      * XML方式 查询订单物流轨迹
 72      * @throws Exception 
 73      */
 74     public String getOrderTracesByXml() throws Exception{
 75         String requestData= "<?xml version="1.0" encoding="utf-8" ?>" 
 76                             "<Content>" 
 77                             "<OrderCode></OrderCode>" 
 78                             "<ShipperCode>SF</ShipperCode>" 
 79                             "<LogisticCode>589707398027</LogisticCode>" 
 80                             "</Content>";
 81         
 82         Map<String, String> params = new HashMap<String, String>();
 83         params.put("RequestData", urlEncoder(requestData, "UTF-8"));
 84         params.put("EBusinessID", EBusinessID);
 85         params.put("RequestType", "1002");
 86         String dataSign=encrypt(requestData, AppKey, "UTF-8");
 87         params.put("DataSign", urlEncoder(dataSign, "UTF-8"));
 88         params.put("DataType", "1");
 89         
 90         String result=sendPost(ReqURL, params);    
 91         
 92         //根据公司业务处理返回的信息......
 93         
 94         return result;
 95     }
 96  
 97     /**
 98      * MD5加密
 99      * @param str 内容       
100      * @param charset 编码方式
101      * @throws Exception 
102      */
103     @SuppressWarnings("unused")
104     private String MD5(String str, String charset) throws Exception {
105         MessageDigest md = MessageDigest.getInstance("MD5");
106         md.update(str.getBytes(charset));
107         byte[] result = md.digest();
108         StringBuffer sb = new StringBuffer(32);
109         for (int i = 0; i < result.length; i  ) {
110             int val = result[i] & 0xff;
111             if (val <= 0xf) {
112                 sb.append("0");
113             }
114             sb.append(Integer.toHexString(val));
115         }
116         return sb.toString().toLowerCase();
117     }
118     
119     /**
120      * base64编码
121      * @param str 内容       
122      * @param charset 编码方式
123      * @throws UnsupportedEncodingException 
124      */
125     private String base64(String str, String charset) throws UnsupportedEncodingException{
126         String encoded = base64Encode(str.getBytes(charset));
127         return encoded;    
128     }    
129     
130     @SuppressWarnings("unused")
131     private String urlEncoder(String str, String charset) throws UnsupportedEncodingException{
132         String result = URLEncoder.encode(str, charset);
133         return result;
134     }
135     
136     /**
137      * 电商Sign签名生成
138      * @param content 内容   
139      * @param keyValue Appkey  
140      * @param charset 编码方式
141      * @throws UnsupportedEncodingException ,Exception
142      * @return DataSign签名
143      */
144     @SuppressWarnings("unused")
145     private String encrypt (String content, String keyValue, String charset) throws UnsupportedEncodingException, Exception
146     {
147         if (keyValue != null)
148         {
149             return base64(MD5(content   keyValue, charset), charset);
150         }
151         return base64(MD5(content, charset), charset);
152     }
153     
154      /**
155      * 向指定 URL 发送POST方法的请求     
156      * @param url 发送请求的 URL    
157      * @param params 请求的参数集合     
158      * @return 远程资源的响应结果
159      */
160     @SuppressWarnings("unused")
161     private String sendPost(String url, Map<String, String> params) {
162         OutputStreamWriter out = null;
163         BufferedReader in = null;        
164         StringBuilder result = new StringBuilder(); 
165         try {
166             URL realUrl = new URL(url);
167             HttpURLConnection conn =(HttpURLConnection) realUrl.openConnection();
168             // 发送POST请求必须设置如下两行
169             conn.setDoOutput(true);
170             conn.setDoInput(true);
171             // POST方法
172             conn.setRequestMethod("POST");
173             // 设置通用的请求属性
174             conn.setRequestProperty("accept", "*/*");
175             conn.setRequestProperty("connection", "Keep-Alive");
176             conn.setRequestProperty("user-agent",
177                     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
178             conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
179             conn.connect();
180             // 获取URLConnection对象对应的输出流
181             out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
182             // 发送请求参数            
183             if (params != null) {
184                   StringBuilder param = new StringBuilder(); 
185                   for (Map.Entry<String, String> entry : params.entrySet()) {
186                       if(param.length()>0){
187                           param.append("&");
188                       }                  
189                       param.append(entry.getKey());
190                       param.append("=");
191                       param.append(entry.getValue());                      
192                       //System.out.println(entry.getKey() ":" entry.getValue());
193                   }
194                   //System.out.println("param:" param.toString());
195                   out.write(param.toString());
196             }
197             // flush输出流的缓冲
198             out.flush();
199             // 定义BufferedReader输入流来读取URL的响应
200             in = new BufferedReader(
201                     new InputStreamReader(conn.getInputStream(), "UTF-8"));
202             String line;
203             while ((line = in.readLine()) != null) {
204                 result.append(line);
205             }
206         } catch (Exception e) {            
207             e.printStackTrace();
208         }
209         //使用finally块来关闭输出流、输入流
210         finally{
211             try{
212                 if(out!=null){
213                     out.close();
214                 }
215                 if(in!=null){
216                     in.close();
217                 }
218             }
219             catch(IOException ex){
220                 ex.printStackTrace();
221             }
222         }
223         return result.toString();
224     }
225     
226     
227     private static char[] base64EncodeChars = new char[] { 
228         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 
229         'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 
230         'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 
231         'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 
232         'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
233         'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
234         'w', 'x', 'y', 'z', '0', '1', '2', '3', 
235         '4', '5', '6', '7', '8', '9', ' ', '/' }; 
236     
237     public static String base64Encode(byte[] data) { 
238         StringBuffer sb = new StringBuffer(); 
239         int len = data.length; 
240         int i = 0; 
241         int b1, b2, b3; 
242         while (i < len) { 
243             b1 = data[i  ] & 0xff; 
244             if (i == len) 
245             { 
246                 sb.append(base64EncodeChars[b1 >>> 2]); 
247                 sb.append(base64EncodeChars[(b1 & 0x3) << 4]); 
248                 sb.append("=="); 
249                 break; 
250             } 
251             b2 = data[i  ] & 0xff; 
252             if (i == len) 
253             { 
254                 sb.append(base64EncodeChars[b1 >>> 2]); 
255                 sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); 
256                 sb.append(base64EncodeChars[(b2 & 0x0f) << 2]); 
257                 sb.append("="); 
258                 break; 
259             } 
260             b3 = data[i  ] & 0xff; 
261             sb.append(base64EncodeChars[b1 >>> 2]); 
262             sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); 
263             sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]); 
264             sb.append(base64EncodeChars[b3 & 0x3f]); 
265         } 
266         return sb.toString(); 
267     }
268 }

 

本文由澳门新葡8455手机版发布于计算机编程,转载请注明出处:数量接口发掘,物流查询

上一篇:PHP编程快速实现数组去重的方法详解_php技巧_脚本 下一篇:没有了
猜你喜欢
热门排行
精彩图文