【12306】登陆流程实现(微信小程序 + php)

好像很久之前写过一篇爬12306登录接口的帖子,没写完,今天就接着来写了.

接口及大致流程见  →→→接口说明

这篇直接上代码

首先是php代码中最重要的get请求方法!!!

/**
 * get请求方法
 * @param $url
 * @param array $_header
 * @return bool|mixed
 */
function get( $url, $_header = [] ,$cookie_path = '')
{
    //(假装浏览器请求)
    $_header = array_merge($_header,[
        'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
        'Connection:keep-alive',
        'Accept-Language:zh-CN,zh;q=0.8',
        'Accept-Encoding:gzip, deflate, br',
        'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Upgrade-Insecure-Requests:1'
    ]);

    $curl = curl_init();
    if( stripos($url, 'https://') !==FALSE )
    {
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    }
    //这个很重要
    if(!empty($cookie_path)){
        //访问时带上cookie文件里的内容转成cookie字符串附加在请求头里面
        curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_path);
        //这个是把响应的cookie存进cookie保存起来
        curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_path);
    }

    //这个是针对12306响应内容 乱码的处理
    curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate');
    //设置请求链接
    curl_setopt($curl, CURLOPT_URL, $url);

    //是否返回响应头,若是,返回的$res字符串前面会加上响应头
    curl_setopt($curl, CURLOPT_HEADER, 0);
    //是否返回请求头,请求结束后 配合 curl_getinfo($curl,CURLINFO_HEADER_OUT)使用
    //curl_setopt($curl, CURLINFO_HEADER_OUT, 0);

    //响应内容不直接输出
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    //设置请求头
    if ( !empty($_header ))
    {
        curl_setopt($curl, CURLOPT_HTTPHEADER, $_header);
    }
    $ret    = curl_exec($curl);
    //$info   = curl_getinfo($curl,CURLINFO_HEADER_OUT);
    curl_close($curl);
    return $ret;
}

然后是服务端接口代码

    /**
     * 获取图片,并输出至客户端
     */
    function getImg(){
        $url = 'https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand';
        $res = get($url,[],$this->cookie_file);
        //设置响应头,保证以图片格式输出
        header('Content-Type:image/png');
        exit($res);
    }
    /**
     * 校验图片
     * @return array
     */
    function getToken(){
        $point = request()->get('answer', '');
        $url = 'http://kyfw.12306.cn/passport/captcha/captcha-check?answer='.$point;
        $res = get($url,[],$this->cookie_file);
        $res = $this->formatRes($res);
        header('content-type:application/json');
        //校验成功的状态码是4
        if($res['result_code'] == 4){
            return $this->login();
        }
        exit(json_encode($res));
    }
    /**
     * 登录
     * @return array
     */
    function login(){
        try {
            //$res = post($url, $param, 'json', [], $this->cookie_file);
            $login_url = 'http://kyfw.12306.cn/passport/web/login?username=账号&password=密码&appid=otn';
            $res = get($login_url,[],$this->cookie_file);
            $res = $this->formatRes($res);
            if($res['result_code'] == 0){
                //登陆成功啦
                //这个东西,下集再讲
                $vip = $res['uamtk'];
            }
            header('content-type:application/json');
            exit(json_encode($res));

        }catch (\Exception $e){
            $code = $e->getCode();
            return [
                'code'=>empty($code)?ERR_CODE_PARAM:$code,
                'data'=>[],
                'msg'=>$e->getMessage(),
            ];
        }
    }
    /**
     * 处理相应数据
     * @param $res
     * @return mixed|\SimpleXMLElement
     */
    function formatRes($res){
        //脑抽的12306返回的数据可能是xml也可能是json字符串
        //所以要处理下结果
        $json = json_decode($res,1);
        if(empty($json)){
            $json = simplexml_load_string($res);
        };
        return $json;
    }

关于cookie_file变量你们自行替换成cookie文件保存目录

最后是小程序代码

var that;
var app = getApp();
Page({
  /**
   * 页面的初始数据
   */
  data: {
    time:new Date().getTime(),
    pont_list: [
    ],
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    that = this;
  },
  /**
   * 删除点
   */
  removePont(e) {
    let key = e.currentTarget.dataset.key;
    let pont_list = that.data.pont_list;
    pont_list.splice(key, 1);
    that.setData({
      pont_list: pont_list
    })
  },
  /**
   * 点击图片
   */
  clickImg(e) {
    console.log(e.detail.x, e.detail.y)
    let pont_list = that.data.pont_list;
    e.detail.y = e.detail.y - 30;
    pont_list.push({
      x: e.detail.x,
      y: e.detail.y,
      pont_x: e.detail.x - 10,
      pont_y: e.detail.y - 10 + 30,//10是圆点的半径 30是距离顶部的高(也就是图片上提示文字的高度)
    })
    that.setData({
      pont_list: pont_list
    })
    console.log(e.detail.x, e.detail.y)
  },
  save() {
    let pont_list = that.data.pont_list;
    if (pont_list.length <= 0) {
      wx.showToast({
        title: '请按提示勾选',
      })
      return false;
    }
    let answer = [];
    for (var x in pont_list) {
      answer.push(pont_list[x].x);
      answer.push(pont_list[x].y);
    }
    let param = {
      login_site: "E",
      rand: "jsrand",
      answer: answer.join(',')
    };
    app.get({
      url: "http://txx.laravel.com/Train/getToken",
      data: {
        answer: answer.join(',')
      },
      success: function (e) { console.log(e) }
    });
  },
})
/*覆盖层,遮住验证图片,记录点击数据*/
.mark{
  position: absolute;
  height:160px;
  width:294px;
  z-index:99;
  top:30px;
}

image{
  width:294px;
  height:190px;
}
.pont{
  z-index:100;
  width:20px;
  height:20px;
  border-radius: 50%;
  background-color: red;
  position: absolute;
}
<view id="main">
<image src="http://txx.laravel.com/Train/getImg?token={{time}}"></image>
<view class="mark" bindtap='clickImg'></view>
<view class="pont" style="left:{{item.pont_x}}px;top:{{item.pont_y}}px;" bindtap="removePont" wx:for-index="key" wx:for="{{pont_list}}" wx:item="item" data-key="{{key}}"></view>
</view>
<button bindtap="save">确认</button>

简单介绍下小程序页面结构

最后的最后晒一下"登陆成功"几个字

睡觉睡觉

发布了35 篇原创文章 · 获赞 18 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/TXX_c/article/details/84947363