http 登录优购

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("")

	// 匹配到结果集
	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,go,http)