• 使用 golang 辅助查询网约车信息


    前些日子,收到一个做网约车的朋友的需求,他手下目前有几百号司机和车子。每隔1个月需要去交警队官方网站查询车和人的信息:

    车:是否预约出租客运

    人:是否有从业资格

     

    流程大致如下:

    1. 内部系统调用本服务,传入车和人的信息

    2. 本服务去交管局网站查询

    难点在于查询网站有个验证码,当然这也是他请我帮忙做的原因吧,谈好价格后,开干!

    大致解决方案:

    1. 使用 golang 搭建一个web站点

    2. 接受参数后,去交管局网站查询

    3. 模拟访问查询网站,下载验证码和cookie

    4. 破解验证码

    5. 模拟查询网站提交查询信息

    6. 返回查询结果给调用者

    验证码我使用的是百度AI文字识别方案,经测试,识别效果很好,但是有日使用次数限制。

     

    部分源代码:

    package openapi
    
    import (
    	"fmt"
        "strings"
        // "strconv"
    	// "bytes"
        "os"
        // "io"
    	"net/http"
    	"net/url"
    	// "time"
    	"io/ioutil"
    	"encoding/json"
    	"encoding/base64"
    	"errors"
    	"github.com/astaxie/beego"
    )
    
    type BaiduAI struct {
    	ApiKey string
    	SecretKey string
    }
    
    func (this *BaiduAI) setApi(){
    	this.ApiKey = "###"
    	this.SecretKey = "###"
    }
    
    func (this *BaiduAI) GetToken() (string, error){
    	if len(this.ApiKey) == 0{
    		this.setApi()
    	}
    
    	//beego.AppConfig.Set("baidu_ai_access_token", this.SecretKey)
    	str := beego.AppConfig.String("baidu_ai_access_token")
    
    	if str  != "0"{
    		return str , nil
    	}
    
    	urlstr := "https://aip.baidubce.com/oauth/2.0/token"
    	v := url.Values{}
        v.Add("client_id", this.ApiKey)
    	v.Add("client_secret", this.SecretKey)
    	v.Add("grant_type", "client_credentials")
        param := v.Encode()
    	reqest, _ := http.NewRequest("POST", urlstr, strings.NewReader(param))
    	reqest.Header.Add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
       
    	client := &http.Client{}
    	response, err := client.Do(reqest)
    	if(err != nil){
    	   defer response.Body.Close()
    	   return "", err
    	}
    	
    	body, _ := ioutil.ReadAll(response.Body)
    	content := string(body)
    	fmt.Println("BAIDU API TOKEN :" , content)
    
    	m := map[string]interface{}{}
    	errx := json.Unmarshal([]byte(content), &m)
    
    	if errx != nil {
    		return "", errx
    	}
    
    	token := m["access_token"].(string)
    	beego.AppConfig.Set("baidu_ai_access_token", token)
    	return token, nil
    }
    
    func (this *BaiduAI) TryGetBase64Captcha(path string) (string, error){
    	// File
    	file, err := os.Open(path)
    	if err != nil {
    		fmt.Println("打开图片出错", err)
    		fmt.Println(err)
    		os.Exit(-1)
    	}
    	defer file.Close()
    
        // FileInfo
    	stats, err := file.Stat()
        if err != nil {
            return "", err
    	}
    
    	// []byte
        data := make([]byte, stats.Size())
        _, err = file.Read(data)
        if err != nil {
             return "", err
        }
    
    	base64str := base64.StdEncoding.EncodeToString(data)
    	fmt.Println("data:image/jpg;base64,", base64str)
    
    	return base64str, nil
    }
    
    // 尝试解开图形验证码
    func (this *BaiduAI) TryGetCaptchaValue(path string) (string, error){
    
    	base64, err := this.TryGetBase64Captcha(path)
    	if err != nil{
    		return "", err
    	} 
    
    	access_token, err := this.GetToken()
    	if err != nil{
    		return "", err
    	}
    
    	// doc page : https://ai.baidu.com/ai-doc/OCR/Ok3h7y1vo
    
    	urlstr := "https://aip.baidubce.com/rest/2.0/ocr/v1/numbers?access_token=" + access_token
    	v := url.Values{}
    	v.Add("recognize_granularity", "big")
    	v.Add("detect_direction", "false")
    	v.Add("image", base64)
    	param := v.Encode()
    	
    	reqest, _ := http.NewRequest("POST", urlstr, strings.NewReader(param))
    	reqest.Header.Add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
       
    	client := &http.Client{}
    	response, err := client.Do(reqest)
    	if(err != nil){
    	   defer response.Body.Close()
    	   return "", err
    	}
    	
    	body, _ := ioutil.ReadAll(response.Body)
    	content := string(body)
    	fmt.Println("百度AI 图片识别结果 :" , content)
     
    	return this.readJson(content)
    }
    
    func (this *BaiduAI) readJson(jsonstr string) (string, error){
    
    	map_result := map[string]interface{}{}
    	errx := json.Unmarshal([]byte(jsonstr), &map_result)
    	if errx != nil {
    		return "", errx
    	}
    
    	words_result_num, ok := map_result["words_result_num"]
    	if !ok {
    		return jsonstr, nil
    	}
    
    	int_nm := words_result_num.(float64)
    
    	if int_nm == 0 {
    		return "", errors.New("未能识出此验证码,请重试")
    	}
    
    	words_result := map_result["words_result"]
    
    	arr_result := words_result.([]interface{})
    	fmt.Println(arr_result[0]);
    
    	map_end := arr_result[0].(map[string]interface {})
    
    	
    	fmt.Println("2222222222222222222222222222222222222");
    	fmt.Println(map_end["words"].(string));
    
    	words := map_end["words"].(string)
    
    	return words, nil
    }
    

      

  • 相关阅读:
    进程和线程
    进程通信、同步与调度
    文件和文件系统
    【nexys3】【verilog】小设计——拆弹游戏
    Qt4开发环境搭建(Qt4.8.7+mingw4.8.2+Qt Creator4.2.0)
    GPL和LGPL
    【rpi】使用putty远程连接rpi(ssh)
    mysql 命令 小结
    安装mysql zip 安装包 Navicat连接
    python虚拟环境 virtualenv工具
  • 原文地址:https://www.cnblogs.com/chenrh/p/12027824.html
Copyright © 2020-2023  润新知