百万英雄/冲刺大会等答题助手

 PHP进阶  2018-08-14  admin  13456  18165

adb工具截取手机屏幕,发送截图到电脑,PHP截取文字部分,调用Google的开源的OCR识别工具Tesseract-OCR,转为文字,调用百度搜索题目和答案,根据题目加选项的结果数量和首页出现的次数,综合判断给出答案。

浏览器输出结果

<?php

class SearchAnswer
{

    const WORK_DIR = __DIR__;
    //tesseract 路径
    private static $tesseract_path = '"'. WORK_DIR.'"\tool\Tesseract-OCR\tesseract" ';
    //语言包目录和参数
    private static $tessdata = ' --tessdata-dir "D:\dev\Tesseract-OCR\tessdata" ';
    private static $lang = ' -l chi_sim  --psm 6 ';

    //截图文字区域
    //private static $question_pos = array(80, 320, 1000, 1200);     //百万英雄
    private static $question_pos = array(120, 320, 1000, 1200);     //百万英雄
    //$question_pos = array(80, 400, 1000, 1300);     //腾讯
    //$question_pos = array(80, 320, 1000, 1100);     //百度 好看视频

    const BROWSER = '"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"';
    private static $negative_words_arr = ['不是', '没有', '不属于', '不在', '不会', '不需要', '不包含', '不准确', '不可能', '不途经', '不包括', '不正确', '不作为', '错误', '不适合', '不应该', '不相当', '无关', '不相符'];

    /**
     * 手机截图并推送到pc
     * @return string
     */
    /*因为PC端adb默认开启USB调试的,故这里必须先杀掉adb服务,如下命令:
    adb kill-server
    然后,通过命令连接设备ip和端口,如上图所示:
    adb connect 192.168.1.4:5555
    最后,如果要断开连接,则
    adb disconnect*/
    static function screencap()
    {
        $new_file = self::WORK_DIR . '/question/screen.png';
        shell_exec('adb shell screencap -p | perl -pe "s/\x0D\x0A/\x0A/g" > ' . $new_file);  //cmder  下
        return $new_file;
    }

    /**
     * 截取手机截图的问题和选项区域,并生成图片
     * @param $src_img
     * @param string $file_name
     * @return string
     */
    static function getImg($src_img, $file_name = 'question')
    {
        $dst_w = self::$question_pos[2] - self::$question_pos[0];
        $dst_h = self::$question_pos[3] - self::$question_pos[1];
        //只处理png截图 剪裁
        $src_im = imagecreatefrompng($src_img);
        $dst_im = imagecreate($dst_w, $dst_h);
        //$dst_im = imagecreatetruecolor($dst_w, $dst_h);
        imagecopy($dst_im, $src_im, 0, 0, self::$question_pos[0], self::$question_pos[1], $dst_w, $dst_h);
        //$file_name = dirname($src_img) . "/$file_name.png";
        $file_name2 = self::WORK_DIR . '/question/' . $file_name . '.png';

        imagepng($dst_im, $file_name2);
        imagedestroy($dst_im);
        return $file_name2;
    }


    /**
     * 获取图片的题目和选项
     * @param $ocr_img
     * @param string $ocr_text
     * @return array    题目和选项
     */
    static function getOcrText($ocr_img, $ocr_text = 'question')
    {

        $output = self::WORK_DIR . "/question/$ocr_text";
        $tessdata_cmd = self::$tesseract_path . $ocr_img . ' ' . $output . self::$tessdata . self::$lang . '  >log.log 2>log2.log';
        shell_exec($tessdata_cmd);
        $text = file_get_contents($output . '.txt');
        $text = trim($text, "\n\f");
        //一 识别为_
        $text = str_replace([' ', '_'], ['', '一'], $text);
        $text_arr = array_filter(explode("?\n", $text));
        $question = preg_replace('/^([0-9oO]+\.)/', '', $text_arr[0]);
        //$choices_arr = explode("\n", $text_arr[1]);
        $choices_arr = array_filter(explode("\n", $text_arr[1]), function ($var) {
            if (!empty($var)) {
                return $var;
            } else {
                return false;
            }
        });
        $choices_arr = array_values($choices_arr);
        return array('question' => str_replace(["\n"], [''], $question), 'choices' => $choices_arr);
    }

//    function array_empty($var)
//    {
//        if (!empty($var)) {
//            return $var;
//        } else {
//            return false;
//        }
//    }

    static function search_result($content, $info)
    {
        //$content = "百度为您找到相关结果约41,900,000个";
        //$content = getCurlSearch($url);
        //$content = curl_get_https($url);
        $pattern = "/百度为您找到相关结果约([\d\,]*)个/";
        preg_match($pattern, $content, $match);
        $search_amount['choices'] = $info;
        $search_amount['count'] = str_replace(',', '', $match[1]);
        $search_amount['count2'] = substr_count($content, $info);
        return $search_amount;
    }


    /**
     * 打开浏览器搜索
     * @param $info
     */
    static function methodOne($info)
    {
        $baidu = ' http://www.baidu.com/s?wd="' . $info['question'] . '"';
        system(self::BROWSER . $baidu);
    }

    static function methodTwo($info)
    {
        //问题去掉否定词
        $negative_words_arr2 = self::negativeWords(self::$negative_words_arr);
        $question = str_replace(self::$negative_words_arr, [' '], $info['question'], $negative_words_count);
        $title = '<h2 class="round">&nbsp;</h2>';
        $question2 = $info['question'];
        if ($negative_words_count > 0) {
            $title = "<h4 style='color: red;' class='title'>否定词</h4>";
            $question2 = str_replace(self::$negative_words_arr, $negative_words_arr2, $info['question']);
        }
        //$title .= '<h3 class="title">' . $info['question'] . '</h3>';
        $title .= '<h3 class="title">' . $question2 . '</h3>';
        $options = '';
        $url_arr = [];
        foreach ($info['choices'] as $key => $val) {
            //$param = $info['question'] . ' +' . $val;
            $param = $question . ' +' . $val;
            $param = urlencode($param);
            $url_arr[] = 'https://www.baidu.com/s?wd=' . $param;
        }
        $result = self::multi_get($url_arr, $info);
        $count = [];
        $count = array_column($result, 'count');
        $max = max($count);
        $min = min($count);
        $count2 = array_column($result, 'count2');
        $max2 = max($count2);
        $min2 = min($count2);
        foreach ($result as $k => $v) {
            $this_answer = '';
            $answer_one = '';
            $answer_two = '';
            if ($negative_words_count == 0 && $v['count2'] == $max2) {
                $answer_two = 'class="two"';
                $this_answer = 'class="this_answer"';
            } elseif ($negative_words_count > 0 && $v['count2'] == $min2) {
                $answer_two = 'class="two"';
                $this_answer = 'class="this_answer"';
            }
            if ($negative_words_count == 0 && $v['count'] == $max) {
                $answer_one = 'class="one"';
            } elseif ($negative_words_count > 0 && $v['count'] == $min) {
                $answer_one = 'class="one"';
            }
            $options .= "<p class='answer'><span $this_answer>{$v['choices']} </span>  <span class='score'><span $answer_one>{$v['count']} </span>  首页:<span $answer_two>{$v['count2']} </span></span></p>";
        }
        echo $title . $options;
    }

    /**
     * @param $url
     * @return mixed|string
     */
    static function getCurlSearch($url)
    {
        $content = "错误信息";
        if (function_exists('curl_init')) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
            //curl_setopt($ch, CURLOPT_USERAGENT, _USERAGENT_);
            curl_setopt($ch, CURLOPT_REFERER, "http://www.baidu.com/");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            //curl_setopt($ch, CURLOPT_COOKIESESSION, true);
            curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36");
            $content = curl_exec($ch);
            curl_close($ch);

        }
        return $content;
    }

    /**
     * @param $url
     * @return mixed
     */
    static function curl_get_https($url)
    {
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
        //curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);  // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36");
        $tmpInfo = curl_exec($curl);     //返回api的json对象
        //关闭URL请求
        curl_close($curl);
        return $tmpInfo;    //返回json对象
    }

    /**
     * @param $url
     * @param $info
     * @return array
     */
    static function multi_get($url, $info)
    {
        $chs = array();
        $result = array();
        $mh = curl_multi_init();
        foreach ($url as $val) {
            $ch = curl_init();
            $chs[] = $ch;
            //$this->prepare($ch);
            curl_setopt($ch, CURLOPT_URL, $val);
            //curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            //curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36");
            curl_multi_add_handle($mh, $ch);
        }
        $running = null;
        do {
            curl_multi_exec($mh, $running);
            usleep(100);
        } while ($running);

        foreach ($chs as $k => $ch) {
            $content = curl_multi_getcontent($ch);
            //$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            //echo $content;
            //file_put_contents(time().rand(1000,9999).'.html',$content);
            $result[] = self::search_result($content, $info['choices'][$k]);
            curl_multi_remove_handle($mh, $ch);
        }
        curl_multi_close($mh);
        return $result;
    }

    /**
     * 处理否定词
     * @return array
     */
    static function negativeWords()
    {
        $negative_words_arr2 = array_map(function ($val) {
            return "<span style='color: red'>$val</span>";
        }, self::$negative_words_arr);
        return $negative_words_arr2;
    }

    /**
     * 运行
     */
    static function run()
    {
        $screencap = self::screencap();
        //$screencap = 'F:\dati\question\screen.png';
        $question_img = self::getImg($screencap);
        $question = self::getOcrText($question_img);
        self::methodTwo($question);
        file_put_contents(self::WORK_DIR . '/question/options', json_encode($question, JSON_UNESCAPED_UNICODE));
    }

}


dati.zip


转载必须注明出处:

百万英雄/冲刺大会等答题助手 —— centphp