使用swoole倒计时查询火车票

337 阅读2分钟
原文链接: zhuanlan.zhihu.com

国庆节到了,一直也未能守在12306面前抢票,所以写了个脚本,调第三方的api挨个的查询有没有余票,有余票立马给我发短信或者微信通知。帖下代码。

#!/usr/bin/env php
<?php

function wlog($msg)
{

    echo "[" . date("Y-m-d H:i:s", time()) . "]\t" . $msg . PHP_EOL;

}


class Play
{


    public $i = 0;

    /* 可配置项 开始 - --------------*/

    public $time = 0.1 ; // 多少分钟执行一次

    // https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
    public $appid = "xxxxxxxxxxxxxxxx"; // 微信沙盒的appid
    // 微信沙盒的appsecret
    public $appsk = "xxxxxxxxxxxxxxxxxxxxxxx";
    // 关注了测试号以后,再沙盒里面查找你需要通知的用户的appid,
    // 能正确通知的前提是,在48小时内要与该测试号随便发一条消息就行了,
    // 不然微信不让发通知。
    public $openid
        = [
            "xxxxxxxxxxxxxxx",
        ];

    // 短信通知列表  这是短信宝的短信通知,当然也可以用其他平台。
    public $mobile
        = [
            "15800000000",
        ];

    // 程序崩溃不通知名单列表
    public $denyList
        = [
            "15811111111", // openid 
        ];
    // 需要查票的类型 . D动车,K快车,T特快,G高铁. 
    public $type = ["D", "K", "G"];
    // 下面不用解释了吧,key, dtype不用变
    public $config
        = [
            "start" => '成都',
            'end'   => '南昌',
            'date'  => '2017-10-01',
            'dtype' => 'json',
            'key'   => 'c65caba9caeb60c4b1c192ca565af196',
        ];
    // 如果不想用短信把这个true改成false
    public $enableSms = true;
    // 短信宝 账户
    public $smsName = "";
    // 短信宝 密码
    public $smsPass = "";


    /* 可配置项 end - --------------*/


    /* 下面的不需要动了 */

    public $accessToken = null;
    public $expirs_in = 0;

    public function __construct()
    {
        $this->run($this->time);
    }


    public function run($time)
    {
         if(extension_loaded('swoole'))
        {

            swoole_timer_tick(1000 * 60 * $time, [$this, 'find']);
        }
        else{
            wlog("[警告] swoole 扩展不存在,请用crontab执行!");
            wlog("crontab -e");
            wlog("*/20 * * * * php /path/to/server.php");
            wlog("service crond restart");
            wlog("每20分钟执行一次");
            $this->find();
        }
    }


    public function find()
    {
        $this->i++;
        try {
            wlog("系统第" . $this->i . "次运行");
            $url     = "http://apis.juhe.cn/train/s2swithprice?" . http_build_query($this->config);
            $content = json_decode(file_get_contents($url), true);
            if (isset($content ['error_code']) && $content ['error_code'] != 0) {
                // 请求失败, 需要通知我,
                $this->msg("接口炸了");
                $this->sendMsgToUser("接口炸了");

                return;
            }
            $list = $content ['result']['list'];
            foreach ($list as $value) {
                if (in_array(strtoupper($value ['train_type']), $this->type)) // 动车是D  快车是L  高铁是G
                {
                    wlog("有票::" . json_encode($value));
                    $this->msg("擦,有票了,赶紧买!!" . $value ['train_no']);
                    $this->sendMsgToUser("擦,有票了,赶紧买!!" . $value ['train_no']);
                }
            }
        }
        catch (\Exception $e) {
            wlog('捕获了一个异常' . $e->getMessage() . "继续运行");
        }
    }

    public function msg($content)
    {
        if(!$this->enableSms)
        {
            return ;
        }
        $name = $this->smsName;
        $pass = md5($this->smsPass);

        foreach ($this->mobile as $m) {
            if(!in_array($m ,$this->denyList))
            {
                $u1 = sprintf("http://api.smsbao.com/sms?u=%s&p=%s&m=%s&c=%s", $name, $pass, $m, $content);
                file_get_contents($u1);
            }
        }
    }


    function getAk()
    {
        if (time() < $this->expirs_in && $this->accessToken != null) {
            return $this->accessToken;
        }
        $url             = sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
            $this->appid,
            $this->appsk
        );
        $res             = json_decode(file_get_contents($url), true);
        $this->expirs_in = time() + 7200;

        return $this->accessToken = $res ['access_token'];
    }

    function sendMsgToUser($msg)
    {

        $ak  = $this->getAk();
        $url = sprintf("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s", $ak);

        foreach ($this->openid as $value) {
            if(!in_array($value,$this->denyList)){
                $data     = [
                    "touser"  => $value,
                    "msgtype" => "text",
                    "text"    => [
                        "content" => $msg,
                    ],
                ];
                $data     = json_encode($data, JSON_UNESCAPED_UNICODE);
                $response = $this->post($url, $data); // 发完就行了。
                $r        = json_decode($response, true);
                if ($r ['errcode'] != '0') {
                    wlog("微信推送失败::" . $response);
                }
            }
        }
    }

    public function post($url, $data)
    {
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)'); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_TIMEOUT, 30);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $tmpInfo = curl_exec($curl);
        if (curl_errno($curl)) {
            echo 'Errno' . curl_error($curl);
        }
        curl_close($curl);

        return $tmpInfo;
    }

}

$play = new Play();

前提得安装swoole拓展,如果没有安装swoole的话,则使用crontab执行就可以了。

*/20 * * * * php /path/to/server.php # 每20分钟执行一次。