您的位置:首页 > 理论基础 > 计算机网络

http 登录优购

2016-05-30 18:25 375 查看
package login

import (
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
)

func New() *Login2Yougou {
return &Login2Yougou{nil, false, 0, nil}
}

type Login2Yougou struct {
client        *http.Client   // client http
isLogin       bool           // 是否成功登录
iSerialNumber uint64         // 流水号,初时值可以固定,但每次请求自增,服务器会效验
cookie        []*http.Cookie // cookies 以便多个client复用
}

//------------------------------------------------------------------------------
// 属性
func (this *Login2Yougou) SetCookies(cok []*http.Cookie) {
this.cookie = cok
}

func (this *Login2Yougou) GetCookies() []*http.Cookie {
return this.cookie
}

func (this *Login2Yougou) GetClient() *http.Client {
return this.client
}

func (this *Login2Yougou) GetLoginResult() bool {
return this.isLogin
}

func (this *Login2Yougou) GetSerialNumber() uint64 {

num := this.iSerialNumber
this.iSerialNumber += 1 // 下次请求流水号要自增1
return num
}

//------------------------------------------------------------------------------
// 操作
// 获取主页html 返回html字符串
func (this *Login2Yougou) getMainPage(url string) (ret string) {

tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}

this.client = &http.Client{Transport: tr}

resp, err := this.client.Get(url)
defer resp.Body.Close()
// 获取失败
if err != nil {
fmt.Println("error:", err)
return ret
}

//fmt.Println(resp)
// 获取成功
arr, err := ioutil.ReadAll(resp.Body)

if err != nil {
fmt.Println("error:", err)
return
}
ret = string(arr)
//this.cookie = resp.Cookies()
this.SetCookies(resp.Cookies())

return ret
}

//  解析主页html 返回序列号,sKey,sValue,解析是否成功
func (this *Login2Yougou) parseMainPage(html string) (iSerialNumber uint64, sKey string, sValue string, err bool) {
// 使用正则进行局部匹配
reg := regexp.MustCompile("<input type=\"hidden\" name=\".{5,20}\" value=\".{2,10}\" id=\"loginNonceId\"/>")

// 匹配到结果集
arr := reg.FindStringSubmatch(html)

for _, subXml := range arr {
//fmt.Println(subXml)

// 查询skey
findPos := strings.Index(subXml, "name=\"")
if findPos != -1 {
findPos += len(string("name=\""))
_subXml := string(subXml[findPos:])

findpos2 := strings.Index(_subXml, "\"")
if findpos2 != -1 {
sKey = string(_subXml[:findpos2])
//fmt.Println(sKey)
}

}

// 查询sValue
findPos = strings.Index(subXml, "value=\"")
if findPos != -1 {
findPos += len(string("value=\""))
_subXml := string(subXml[findPos:])

findpos2 := strings.Index(_subXml, "\"")
if findpos2 != -1 {
sValue = string(_subXml[:findpos2])
//fmt.Println(sValue)
}

}

}

iSerialNumber = 1464312215280
if len(sKey) == 0 || len(sValue) == 0 {
err = false
return
}

err = true
return
}

// 根据用户名密码登录
func (this *Login2Yougou) LoginYougou(userName string, passwd string) bool {
shtml := this.getMainPage("https://passport.yougou.com/signin.jhtml?redirectURL=http://www.yougou.com/")

if len(shtml) == 0 {
fmt.Println("https 请求主页失败")
return false
}

iSerialNumber, sKey, sValue, ret := this.parseMainPage(shtml)
if ret == false {
fmt.Println("获取流水号,键值对失败")
return false
}

fmt.Println(iSerialNumber, sKey, sValue)

////////////////////////////////////////////////////////////////////////////
// 进行login post
loginUrl := "https://passport.yougou.com/my/procsignin.jhtml?callback=" + strconv.FormatUint(iSerialNumber, 10)
fmt.Println(loginUrl)

// 设置form
form := make(url.Values)
form.Set("username", userName)
form.Set("password", passwd)
form.Set("verifycode", "")
form.Set("isVerify", "true")
form.Set(sKey, sValue)
form.Set("callback", "jsonp"+strconv.FormatUint(iSerialNumber, 10))

fmt.Println(form)

// 添加request http info
req, err := http.NewRequest("POST", loginUrl, strings.NewReader(form.Encode()))
req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0")
req.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
req.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("X-Requested-With", "XMLHttpRequest")
req.Header.Add("Connection", "Keep-Alive")
req.Header.Add("Pragma", "no-cache")
req.Header.Add("Cache-Control", "no-cache")

// 复用之前的cookies
for _, cok := range this.GetCookies() {
req.AddCookie(cok)
}

fmt.Println(req)
resp, err := this.client.Do(req)
defer resp.Body.Close()

if err != nil {
fmt.Println("post form失败:", err.Error())
return false
}

arr, err := ioutil.ReadAll(resp.Body)

if err != nil {
fmt.Println("post form返回内容为空 api可能改变:", err.Error())
return false
}

fmt.Println(string(arr))
findPos := strings.Index(string(arr), "login_success")
if findPos == -1 {
fmt.Println("未能登录成功")
return false
} else {
fmt.Println("恭喜你 登录成功")
}

this.isLogin = true

return true
}


main.go[主函数]

package main

import "fmt"
import "login"

func main() {
fmt.Println("主函数")

loginy := login.New()
loginy.LoginYougou("用户名", "密码")
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  go http