gocolly-登录(5)

文章目录

简介

  • 模拟账号密码登录
  • cookie登录
  • 以及字符串cookie登录
  • csrf_token 处理

demo

package main

import (
	"fmt"
	"github.com/gocolly/colly"
	"github.com/gocolly/colly/extensions"
	"log"
	"net/http"
	"os"
	"strings"
	"time"
)

/*
请求执行之前调用
	- OnRequest
响应返回之后调用
	- OnResponse
监听执行 selector
	- OnHTML
监听执行 selector
	- OnXML
错误回调
	- OnError
完成抓取后执行,完成所有工作后执行
	- OnScraped
取消监听,参数为 selector 字符串
	- OnHTMLDetach
取消监听,参数为 selector 字符串
	- OnXMLDetach
*/

// 声明结构类型
type Session struct {
	session *colly.Collector
	file    *os.File
}

// 初始化
func (c *Session) Init() *colly.Collector {
	// 实例化默认收集器
	c.session = colly.NewCollector()

	// 仅访问域
	c.session.AllowedDomains = []string{"quotes.toscrape.com"}

	// 允许重复访问
	c.session.AllowURLRevisit = true

	// 表示抓取时异步的
	// c.session.Async = true
	// 模拟浏览器
	c.session.UserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"

	// 随机UserAgent
	extensions.RandomUserAgent(c.session)

	// 限制采集规则
	/*
		在Colly里面非常方便控制并发度,只抓取符合某个(些)规则的URLS
		colly.LimitRule{DomainGlob: "*.douban.*", Parallelism: 5},表示限制只抓取域名是douban(域名后缀和二级域名不限制)的地址,当然还支持正则匹配某些符合的 URLS

		Limit方法中也限制了并发是5。为什么要控制并发度呢?因为抓取的瓶颈往往来自对方网站的抓取频率的限制,如果在一段时间内达到某个抓取频率很容易被封,所以我们要控制抓取的频率。
		另外为了不给对方网站带来额外的压力和资源消耗,也应该控制你的抓取机制。
	*/
	err := c.session.Limit(&colly.LimitRule{
		// Filter domains affected by this rule
		// 筛选受此规则影响的域
		DomainGlob: "quotes.toscrape.com/*",
		// Set a delay between requests to these domains
		// 设置对这些域的请求之间的延迟
		Delay: 1 * time.Second,
		// Add an additional random delay
		// 添加额外的随机延迟
		RandomDelay: 1 * time.Second,
		// 设置并发
		Parallelism: 5,
	})
	if err != nil {
		fmt.Println(err)
	}

	return c.session
}

// 设置 headers
func (c *Session) setHeaders() {
	header := map[string]string{
		"Accept":     "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
		"Connection": "keep-alive",
		"Host":       "quotes.toscrape.com",
		"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",
	}
	// 在提出请求之前打印 "访问…"
	c.session.OnRequest(func(r *colly.Request) {
		// fmt.Println("Visiting: ", r.URL.String())
		for key, value := range header {
			r.Headers.Add(key, value)
		}
	})
}

// 获取csrf_token
func (c *Session) getCsrfToken() (string, error) {
	url := "http://quotes.toscrape.com/login"

	csrfToken := ""
	c.session.OnHTML("form input[name=\"csrf_token\"]", func(e *colly.HTMLElement) {
		// text
		text := e.Attr("value")
		csrfToken = text
		// fmt.Println("csrfToken: ", csrfToken)
	})

	// fmt.Println("csrfToken: ", csrfToken)

	// 收到响应后
	// c.session.OnResponse(func(r *colly.Response) {
	// 	if r.StatusCode != 200 {
	// 		fmt.Println("访问失败: ", url)
	// 		return
	// 	}
	// 	fmt.Println(string(r.Body))
	// })

	err2 := c.session.Visit(url)
	if err2 != nil {
		fmt.Println(err2)
		return "", err2
	}

	return csrfToken, nil
}

// 登录
func (c *Session) login(csrfToken string) {
	// 访问地址
	url := "http://quotes.toscrape.com/login"

	// 认证
	err := c.session.Post(url, map[string]string{
		"username":   "qqq",
		"password":   "qqq",
		"csrf_token": csrfToken,
	})
	if err != nil {
		log.Fatal(err)
	}

	// 收到响应后
	c.session.OnResponse(func(r *colly.Response) {
		if r.StatusCode != 200 {
			fmt.Println("访问失败: ", url)
		}
		// fmt.Println(r.StatusCode)
		// fmt.Println(r.Headers.Get("Custom-Header"))

	})

	// 开始爬取 url
	err2 := c.session.Visit(url)
	if err2 != nil {
		fmt.Println(err2)
	}
}

// cookie 登录
func (c *Session) cookieLogin() {
	url := "http://quotes.toscrape.com/"

	// 获取cookies
	// fmt.Println(c.session.Cookies(url))

	// 在提出请求之前打印 "访问…"
	c.session.OnRequest(func(r *colly.Request) {
		// 可以添加多个cookie
		cookies := []*http.Cookie{
			{
				Name:  "session",
				Value: "eyJjc3JmX3Rva2VuIjoiR3doU0FqTG5RV3pkTkp2RE1vS1lCZmdPeFJ0VFZGaVVFQ2xYYmtadW1yYVBzeXFwY2VISSIsInVzZXJuYW1lIjoicXFxIn0.EmH1iA.wk6GNffYi6R2vaBhZPLYLBZfwpY",
			},
		}
		err := c.session.SetCookies(url, cookies)
		if err != nil {
			fmt.Println(err)
		}
	})
}

// cookie 登录2
func (c *Session) cookieLogin2() {
	url := "http://quotes.toscrape.com/"

	// 获取cookies
	// fmt.Println(c.session.Cookies(url))

	// 在提出请求之前打印 "访问…"
	c.session.OnRequest(func(r *colly.Request) {
		cookie := "session=eyJjc3JmX3Rva2VuIjoiR3doU0FqTG5RV3pkTkp2RE1vS1lCZmdPeFJ0VFZGaVVFQ2xYYmtadW1yYVBzeXFwY2VISSIsInVzZXJuYW1lIjoicXFxIn0.EmHo_w.pMG9x7Vdwd2INAw1O25NLw6saRk"
		err := c.session.SetCookies(url, setCookieRaw(cookie))
		if err != nil {
			fmt.Println(err)
		}
	})
}


// set cookies raw
func setCookieRaw(cookieRaw string) []*http.Cookie {
	// 可以添加多个cookie
	var cookies []*http.Cookie
	cookieList := strings.Split(cookieRaw, "; ")
	for _, item := range cookieList {
		keyValue := strings.Split(item, "=")
		// fmt.Println(keyValue)
		name := keyValue[0]
		valueList := keyValue[1:]
		cookieItem := http.Cookie{
			Name:  name,
			Value: strings.Join(valueList, "="),
		}
		cookies = append(cookies, &cookieItem)
	}
	return cookies
}

// 首页验证
func (c *Session) getIndex() {
	url := "http://quotes.toscrape.com/"

	c.session.OnHTML(".row.header-box .col-md-4 p a", func(e *colly.HTMLElement) {
		// text
		text := e.Text
		fmt.Println("Logout flag: ", text)
	})

	// 收到响应后
	c.session.OnResponse(func(r *colly.Response) {
		if r.StatusCode != 200 {
			fmt.Println("访问失败: ", url)
		}
		// fmt.Println(string(r.Body))
		// fmt.Println(r.StatusCode)
		// fmt.Println(r.Headers.Get("Custom-Header"))

	})

	err2 := c.session.Visit(url)
	if err2 != nil {
		fmt.Println(err2)
	}
}

func main() {
	s := &Session{}
	// 初始化
	s.Init()

	// 设置 headers
	s.setHeaders()

	// 获取 csrfToken
	// csrfToken, err1 := s.getCsrfToken()
	// if err1 != nil {
	// 	return
	// }
	// fmt.Println("csrf_token: ", csrfToken)
	// 登录1
	// s.login(csrfToken)

	// cookie 登录2
	// s.cookieLogin()

	// cookie 登录3
	s.cookieLogin2()

	// 首页验证
	s.getIndex()

	// 采集等待结束
	s.session.Wait()

	fmt.Println("程序运行结束!")
}

/*
URL already visited
	// 允许重复访问
	c.session.AllowURLRevisit = true
*/
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值