最新消息:VPS服务器又从fzhost.net换回Linode了,主题仍用朋友推荐的大前端D8

【记录】在用go语言成功模拟登陆百度后把相关函数整理至自己的go语言的库函数:crifanLib.go

GO crifan 153浏览 0评论

【背景】

折腾完毕:

【记录】用go语言实现模拟登陆百度

后,接着,就是去把已经写的,通用函数,整理至自己的库函数crifanLib.go中了。

【折腾过程】

1.继续去参考,之前在:

【记录】学习如何写go语言代码

中就学习的:

Your first library

然后去新建对应的文件夹和文件。

2.然后再去build和install:

E:\Dev_Root\go\src\code.google.com\p\crifanLib>go build

E:\Dev_Root\go\src\code.google.com\p\crifanLib>go install

E:\Dev_Root\go\src\code.google.com\p\crifanLib>ls
crifanLib.go  crifanLib.go.bak

3.期间还遇到:

【已解决】go语言中导入另外一个库结果调用时出错:cannot refer to unexported name

4.最后,折腾结果为:

(1)目录结构

go
    pkg
        windows_amd64
            code.google.com
                p
                    crifanLib.a //after install, can see this file
                    log4go.a    //after install, can see this file
    src
        code.google.com
            p
                crifanLib
                    crifanLib.go
                log4go
                    ...
        EmulateLoginBaidu
            EmulateLoginBaidu.go

(2)文件内容:

A. EmulateLoginBaidu.go(注意文件是UTF-8编码)内容如下::

/*
 * [File]
 * EmulateLoginBaidu.go
 * 
 * [Function]
 * 【记录】用go语言实现模拟登陆百度
 * https://www.crifan.com/emulate_login_baidu_using_go_language/
 * 
 * [Version]
 * 2013-09-21
 *
 * [Contact]
 * https://www.crifan.com/about/me/
 */
package main

import (
    "fmt"
    //"builtin"
    //"log"
    //"os"
    "runtime"
    "path"
    "strings"
    "time"
    //"io"
    //"io/ioutil"
    "net/http"
    //"net/http/cookiejar"
    //"net/url"
    //"sync"
    //"net/url"
    "regexp"
    //"bufio"
    //"bytes"
)

import "code.google.com/p/log4go"
//import "code.google.com/p/crifanLib/crifanLib"
import "code.google.com/p/crifanLib"

/***************************************************************************************************
    Global Variables
***************************************************************************************************/
var gLogger log4go.Logger;
var gCurCookies []*http.Cookie;

/***************************************************************************************************
    Functions
***************************************************************************************************/


// Get current file name, without suffix
func getCurFilename() string {
    _, fulleFilename, _, _ := runtime.Caller(0)
    //fmt.Println(fulleFilename)
    var filenameWithSuffix string
    filenameWithSuffix = path.Base(fulleFilename)
    //fmt.Println("filenameWithSuffix=", filenameWithSuffix)
    var fileSuffix string
    fileSuffix = path.Ext(filenameWithSuffix)
    //fmt.Println("fileSuffix=", fileSuffix)
    
    var filenameOnly string
    filenameOnly = strings.TrimSuffix(filenameWithSuffix, fileSuffix)
    //fmt.Println("filenameOnly=", filenameOnly)
    
    return filenameOnly
}
//do init before all others
func initAll(){
    gCurCookies = nil
    gLogger = crifanLib.InitLogger(getCurFilename() + ".log")
}

// //de-init for all
// func deinitAll(){
    // if(nil == gLogger) {
        // gLogger.Close();
        // //os.Stdout.Sync() //try manually flush, but can not fix log4go's flush bug
        
        // gLogger = nil
    // }
// }


func main() {
    initAll()

    gLogger.Info("============ 程序说明 ============");
    gLogger.Info("功能:本程序是用来演示使用Java代码去实现模拟登陆百度");
    gLogger.Info("注意事项:部分百度账户,在登陆时会出现:");
    gLogger.Info("1.部分百度账户,在登陆时会出现:");
    gLogger.Info("系统检测到您的帐号疑似被盗,存在安全风险。请尽快修改密码。");
    gLogger.Info("此时,本程序,无法成功模拟登陆,请自行按照提示去修改密码后,就可以了。");

    //step1: access baidu url to get cookie BAIDUID
    gLogger.Info("====== 步骤1:获得BAIDUID的Cookie ======")
    var baiduMainUrl string = "http://www.baidu.com/";
    gLogger.Debug("baiduMainUrl=%s", baiduMainUrl)
    respHtml := crifanLib.GetUrlRespHtml(baiduMainUrl, nil)
    gLogger.Debug("respHtml=%s", respHtml)
    crifanLib.DbgPrintCookies(crifanLib.GetCurCookies())
    
    //check cookie
    var bGotCookieBaiduid = false;
    //var cookieNameListToCheck []string = ["BAIDUID"]
    //toCheckCookieNameList := [1]string{"BAIDUID"}
    toCheckCookieNameList := []string{"BAIDUID"}
    toCheckCookieNum := len(toCheckCookieNameList)
    gLogger.Debug("toCheckCookieNum=%d", toCheckCookieNum)
    gCurCookies = crifanLib.GetCurCookies()
    curCookieNum := len(gCurCookies)
    gLogger.Debug("curCookieNum=%d", curCookieNum)
    for i := 0; i < toCheckCookieNum; i++ {
        toCheckCkName := toCheckCookieNameList[i];
        gLogger.Debug("[%d]toCheckCkName=%s", i, toCheckCkName)
        for j := 0; j < curCookieNum; j++{
            curCookie := gCurCookies[j]
            if(strings.EqualFold(toCheckCkName, curCookie.Name)){
                bGotCookieBaiduid = true;
                break;
            }
        }
    }

    if bGotCookieBaiduid {
        gLogger.Info("Found cookie BAIDUID");
    }else{
        gLogger.Info("Not found cookie BAIDUID");
    }
    
    //step2: login, pass paras, extract resp cookie
    gLogger.Info("====== 步骤2:提取login_token ======");
    bExtractTokenValueOK := false
    strLoginToken := ""
    var getApiRespHtml string;
    if bGotCookieBaiduid{
        //https://passport.baidu.com/v2/api/?getapi&class=login&tpl=mn&tangram=true
        var getapiUrl string = "https://passport.baidu.com/v2/api/?getapi&class=login&tpl=mn&tangram=true";
        getApiRespHtml = crifanLib.GetUrlRespHtml(getapiUrl, nil);
        gLogger.Debug("getApiRespHtml=%s", getApiRespHtml);
        crifanLib.DbgPrintCookies(crifanLib.GetCurCookies())
        
        //bdPass.api.params.login_token='278623fc5463aa25b0189ddd34165592';
        //use regex to extract login_token
        //【记录】go语言中用正则表达式查找某个值
        //https://www.crifan.com/go_language_regular_expression_find_value/
        loginTokenP, _ := regexp.Compile(`bdPass\.api\.params\.login_token='(?P<loginToken>\w+)';`)
        //loginToken := loginTokenP.FindString(getApiRespHtml);
        //loginToken := loginTokenP.FindSubmatch(getApiRespHtml);
        foundLoginToken := loginTokenP.FindStringSubmatch(getApiRespHtml);
        gLogger.Debug("foundLoginToken=%s", foundLoginToken);
        if nil != foundLoginToken {
            strLoginToken = foundLoginToken[1] //tmp go regexp not support named group, so use index here
            gLogger.Info("found bdPass.api.params.login_token=%s", strLoginToken);
            bExtractTokenValueOK = true;
        } else {
            gLogger.Warn(" not found login_token from html=%s", getApiRespHtml);
        }
    }

    //step3: verify returned cookies
    bLoginBaiduOk := false;
    if bGotCookieBaiduid && bExtractTokenValueOK {
        gLogger.Info("======步骤3:登陆百度并检验返回的Cookie ======");
        staticPageUrl := "http://www.baidu.com/cache/user/html/jump.html";
        
        postDict := map[string]string{}
        //postDict["ppui_logintime"] = ""
        postDict["charset"] = "utf-8"
        //postDict["codestring"] = ""
        postDict["token"] = strLoginToken
        postDict["isPhone"] = "false"
        postDict["index"] = "0"
        //postDict["u"] = ""
        //postDict["safeflg"] = "0"
        postDict["staticpage"] = staticPageUrl
        postDict["loginType"] = "1"
        postDict["tpl"] = "mn"
        postDict["callback"] = "parent.bdPass.api.login._postCallback"

        //【已解决】go语言中获得控制台输入的字符串
        //https://www.crifan.com/go_language_get_console_input_string/
        strBaiduUsername := ""
        strBaiduPassword := ""
        gLogger.Info("Plese input:")
        gLogger.Info("Baidu Username:")
        _, err1 := fmt.Scanln(&strBaiduUsername)
        if nil == err1 {
            gLogger.Debug("strBaiduUsername=%s", strBaiduUsername)
        }
        gLogger.Info("Baidu Password:")
        _, err2 := fmt.Scanln(&strBaiduPassword)
        if nil == err2 {
            gLogger.Debug("strBaiduPassword=%s", strBaiduPassword)
        }
        
        postDict["username"] = strBaiduUsername
        postDict["password"] = strBaiduPassword
        postDict["verifycode"] = ""
        postDict["mem_pass"] = "on"
        
        gLogger.Debug("postDict=%s", postDict)
        
        baiduMainLoginUrl := "https://passport.baidu.com/v2/api/?login";
        loginBaiduRespHtml := crifanLib.GetUrlRespHtml(baiduMainLoginUrl, postDict);
        gLogger.Debug("loginBaiduRespHtml=%s", loginBaiduRespHtml)
        crifanLib.DbgPrintCookies(crifanLib.GetCurCookies());
        
        //check resp cookies exist or not
        cookieNameDict := map[string]bool{
            "BDUSS"     : false,
            "PTOKEN"    : false,
            "STOKEN"    : false,
            //"SAVEUSERID": false, //be deleted
        }

        gCurCookies = crifanLib.GetCurCookies()
        for cookieName, _ := range cookieNameDict {
            for _, singleCookie := range gCurCookies {
                //if(strings.EqualFold(cookieName, singleCookie.Name)){
                if cookieName == singleCookie.Name {
                    cookieNameDict[cookieName] = true;
                    gLogger.Debug("Found cookie %s", cookieName)
                }
            }
        }
        gLogger.Debug("After check resp cookie, cookieNameDict=%s", cookieNameDict)
        
        bAllCookiesFound := true
        for _, bIsExist := range cookieNameDict {
            bAllCookiesFound = bAllCookiesFound && bIsExist
        }
        bLoginBaiduOk = bAllCookiesFound
        if (bLoginBaiduOk) {
            gLogger.Info("成功模拟登陆百度首页!" );
        } else{
            gLogger.Info("模拟登陆百度首页 失败!");
            gLogger.Info("所返回的HTML源码为:" + loginBaiduRespHtml);
        }
    }
    
    // deinitAll()

    //【workaround】go语言中用log4go输出信息时有bug:只输出部分信息,甚至是无任何输出
    //https://www.crifan.com/go_language_log4go_only_output_part_info/
    time.Sleep(100 * time.Millisecond)
}

 

B. crifanLib.go(注意文件是UTF-8编码)内容如下:

/*
 * [File]
 * crifanLib..go
 * 
 * [Function]
 * 【记录】在用go语言成功模拟登陆百度后把相关函数整理至自己的go语言的库函数:crifanLib.go
 * https://www.crifan.com/after_use_go_language_emulate_login_baidu_arrage_common_func_to_crifanlib_go
 * 
 * [Version]
 * 2013-09-21
 *
 * [Contact]
 * https://www.crifan.com/about/me/
 */
package crifanLib

import (
    //"fmt"
    //"log"
    "os"
    //"runtime"
    //"path"
    //"strings"
    "time"
    //"io"
    "io/ioutil"
    "net/http"
    "net/http/cookiejar"
    "net/url"
    //"sync"
    //"net/url"
    //"regexp"
    //"bufio"
    "bytes"
)

//import l4g "log4go.googlecode.com/hg"
//import l4g "code.google.com/p/log4go"
import "code.google.com/p/log4go"

/***************************************************************************************************
    Global Variables
***************************************************************************************************/
var gCurCookies []*http.Cookie;
var gCurCookieJar *cookiejar.Jar;
var gLogger log4go.Logger;

/***************************************************************************************************
    Private Functions
***************************************************************************************************/
//init for crifanLib
func init(){
    gCurCookies = nil
    gCurCookieJar,_ = cookiejar.New(nil)
    gLogger = nil
    
    //InitLogger() // caller should manually call this
}

// //de-init for all
// func deinitAll(){
    // gCurCookies = nil
    // if(nil == gLogger) {
        // gLogger.Close();
        // //os.Stdout.Sync() //try manually flush, but can not fix log4go's flush bug
        
        // gLogger = nil
    // }
// }

/***************************************************************************************************
    Public Functions
***************************************************************************************************/

//init for logger
func InitLogger(logFilename string) log4go.Logger {
    //var filenameOnly string = GetCurFilename()
    //var logFilename string =  filenameOnly + ".log";
    
    //gLogger = log4go.NewLogger()
    //gLogger = make(log4go.Logger)
    
    //for console
    //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter())
    gLogger = log4go.NewDefaultLogger(log4go.INFO)
    
    //for log file
    if _, err := os.Stat(logFilename); err == nil {
        //fmt.Printf("found old log file %s, now remove it\n", logFilename)
        os.Remove(logFilename)
    }
    //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true))
    //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false))
    gLogger.AddFilter("log", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false))
    gLogger.Debug("Current time is : %s", time.Now().Format("15:04:05 MST 2006/01/02"))
    
    return gLogger
}

// //get current logger
// func GetCurLogger() log4go.Logger {
    // return gLogger
// }


//get url response html
func GetUrlRespHtml(strUrl string, postDict map[string]string) string{
    gLogger.Debug("in getUrlRespHtml, strUrl=%s", strUrl)
    gLogger.Debug("postDict=%s", postDict)
    
    var respHtml string = "";
    
    httpClient := &http.Client{
        //Transport:nil,
        //CheckRedirect: nil,
        Jar:gCurCookieJar,
    }

    var httpReq *http.Request
    //var newReqErr error
    if nil == postDict {
        gLogger.Debug("is GET")
        //httpReq, newReqErr = http.NewRequest("GET", strUrl, nil)
        httpReq, _ = http.NewRequest("GET", strUrl, nil)
        // ...
        //httpReq.Header.Add("If-None-Match", `W/"wyzzy"`)
    } else {
        //【记录】go语言中实现http的POST且传递对应的post data
        //https://www.crifan.com/go_language_http_do_post_pass_post_data
        gLogger.Debug("is POST")
        postValues := url.Values{}
        for postKey, PostValue := range postDict{
            postValues.Set(postKey, PostValue)
        }
        gLogger.Debug("postValues=%s", postValues)
        postDataStr := postValues.Encode()
        gLogger.Debug("postDataStr=%s", postDataStr)
        postDataBytes := []byte(postDataStr)
        gLogger.Debug("postDataBytes=%s", postDataBytes)
        postBytesReader := bytes.NewReader(postDataBytes)
        //httpReq, newReqErr = http.NewRequest("POST", strUrl, postBytesReader)
        httpReq, _ = http.NewRequest("POST", strUrl, postBytesReader)
        //httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
        httpReq.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    }
    
    httpResp, err := httpClient.Do(httpReq)
    // ...
    
    //httpResp, err := http.Get(strUrl)
    //gLogger.Info("http.Get done")
    if err != nil {
        gLogger.Warn("http get strUrl=%s response error=%s\n", strUrl, err.Error())
    }
    gLogger.Debug("httpResp.Header=%s", httpResp.Header)
    gLogger.Debug("httpResp.Status=%s", httpResp.Status)

    defer httpResp.Body.Close()
    // gLogger.Info("defer httpResp.Body.Close done")
    
    body, errReadAll := ioutil.ReadAll(httpResp.Body)
    //gLogger.Info("ioutil.ReadAll done")
    if errReadAll != nil {
        gLogger.Warn("get response for strUrl=%s got error=%s\n", strUrl, errReadAll.Error())
    }
    //gLogger.Debug("body=%s\n", body)

    //gCurCookies = httpResp.Cookies()
    //gCurCookieJar = httpClient.Jar;
    gCurCookies = gCurCookieJar.Cookies(httpReq.URL);
    //gLogger.Info("httpResp.Cookies done")
    
    //respHtml = "just for test log ok or not"
    respHtml = string(body)
    //gLogger.Info("httpResp body []byte to string done")

    return respHtml
}

//get current http cookies
func GetCurCookies() []*http.Cookie {
    return gCurCookies
}

//print http cookies
func DbgPrintCookies(httpCookies []*http.Cookie) {
    if nil != httpCookies {
        var cookieNum int = len(httpCookies);
        gLogger.Debug("cookieNum=%d", cookieNum)
        for i := 0; i < cookieNum; i++ {
            var curCk *http.Cookie = httpCookies[i];
            gLogger.Debug("------ Cookie [%d]------", i)
            gLogger.Debug("Name\t\t=%s", curCk.Name)
            gLogger.Debug("Value\t=%s", curCk.Value)
            gLogger.Debug("Path\t\t=%s", curCk.Path)
            gLogger.Debug("Domain\t=%s", curCk.Domain)
            gLogger.Debug("Expires\t=%s", curCk.Expires)
            gLogger.Debug("RawExpires\t=%s", curCk.RawExpires)
            gLogger.Debug("MaxAge\t=%d", curCk.MaxAge)
            gLogger.Debug("Secure\t=%t", curCk.Secure)
            gLogger.Debug("HttpOnly\t=%t", curCk.HttpOnly)
            gLogger.Debug("Unparsed\t=%s", curCk.Unparsed)
            gLogger.Debug("Raw\t\t=%s", curCk.Raw)
        }
    }
}

 

(3)使用方法:

A。先去编译和安装crifanLib.go

E:\Dev_Root\go\src\code.google.com\p\crifanLib>go build

E:\Dev_Root\go\src\code.google.com\p\crifanLib>go install

E:\Dev_Root\go\src\code.google.com\p\crifanLib>

B。运行EmulateLoginBaidu.go即可:

E:\Dev_Root\go\src\EmulateLoginBaidu>go run EmulateLoginBaidu.go
[09/21/13 21:51:04] [INFO] ============ 程序说明 ============
[09/21/13 21:51:04] [INFO] 功能:本程序是用来演示使用Java代码去实现模拟登陆百度
[09/21/13 21:51:04] [INFO] 注意事项:部分百度账户,在登陆时会出现:
[09/21/13 21:51:04] [INFO] 1.部分百度账户,在登陆时会出现:
[09/21/13 21:51:04] [INFO] 系统检测到您的帐号疑似被盗,存在安全风险。请尽快修改密码。
[09/21/13 21:51:04] [INFO] 此时,本程序,无法成功模拟登陆,请自行按照提示去修改密码后,就可以了。
[09/21/13 21:51:04] [INFO] ====== 步骤1:获得BAIDUID的Cookie ======
[09/21/13 21:51:04] [INFO] Found cookie BAIDUID
[09/21/13 21:51:04] [INFO] ====== 步骤2:提取login_token ======
[09/21/13 21:51:05] [INFO] found bdPass.api.params.login_token=23a85f1cdf730fb8ee8c1a7ac0b563b0
[09/21/13 21:51:05] [INFO] ======步骤3:登陆百度并检验返回的Cookie ======
[09/21/13 21:51:05] [INFO] Plese input:
[09/21/13 21:51:05] [INFO] Baidu Username:
xxxxxx
[09/21/13 21:51:10] [INFO] Baidu Password:
yyyyyy
[09/21/13 21:51:12] [INFO] 成功模拟登陆百度首页!

C。当前的EmulateLoginBaidu.go所在目录下,可以生成的对应的log文件:EmulateLoginBaidu.log

且每次运行,之前旧的log文件会删除掉,会新生成对应的log文件的。

5.目前已把对应的库文件:

crifanLib.go

放到之前的crifanLib中了。

详见:

crifanLib中的crifanLib.go

 

【总结】

go中弄个package,也还是有点麻烦的。。。

转载请注明:在路上 » 【记录】在用go语言成功模拟登陆百度后把相关函数整理至自己的go语言的库函数:crifanLib.go

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
19 queries in 0.193 seconds, using 9.90MB memory