介绍
- 本章节搭配结构体的使用,使用类似于类一样的体验;
- OnHTML获取网页信息;
- 实现翻页效果
demo
package main
import (
"fmt"
"github.com/gocolly/colly"
"github.com/gocolly/colly/extensions"
"os"
"strings"
"time"
)
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.UserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"
extensions.RandomUserAgent(c.session)
err := c.session.Limit(&colly.LimitRule{
DomainGlob: "quotes.toscrape.com/*",
// 设置对这些域的请求之间的延迟
Delay: 1 * time.Second,
// Add an additional random delay
// 添加额外的随机延迟
RandomDelay: 1 * time.Second,
// 设置并发
Parallelism: 5,
})
if err != nil {
fmt.Println(err)
}
return c.session
}
// 获取下一页
func (c *Session) getNext(url string) (string, error) {
// 访问地址
// url := "http://quotes.toscrape.com"
// 解析页面
c.getParse()
// 获取下一页
page := ""
// 调用回调函数,获取标签的属性
// pages := ""
c.session.OnHTML(".pager .next a", func(e *colly.HTMLElement) {
// 获取属性值
link := e.Attr("href")
// fmt.Printf("Link found: %q -> %s\n", e.Text, link)
page = link
// 在页面上找到访问链接
// 只有在AllowedDomains中的链接才被访问
// err := c.session.Visit(e.Request.AbsoluteURL(link))
// if err != nil {
// fmt.Println(err)
// }
})
// 错误回调
var err1 error = nil
c.session.OnError(func(_ *colly.Response, err error) {
fmt.Println("Something went wrong:", err)
err1 = err
})
// 开始爬取 url
err2 := c.session.Visit(url)
if err2 != nil {
fmt.Println(err2)
return "", err2
}
return page, nil
}
// 解析页面
func (c *Session) getParse() {
// 在每个 a 标签 href 属性 调用回调函数
c.session.OnHTML(".row .col-md-8 .quote", func(e *colly.HTMLElement) {
// text
text := e.ChildText("span.text")
// fmt.Println("text: ", text)
// author
author := e.ChildText("span .author")
// fmt.Println("author: ", author)
// tags
var tags []string
e.ForEach(".tags a", func(i int, e *colly.HTMLElement) {
text := e.Text
tags = append(tags, text)
})
// fmt.Println("tags: ", tags)
// 保存
c.save(text, author, tags)
})
// 收到响应后
c.session.OnResponse(func(r *colly.Response) {
if r.StatusCode != 200 {
return
}
})
// 在提出请求之前打印 "访问…"
// c.OnRequest(func(r *colly.Request) {
// fmt.Println("Visiting: ", r.URL.String())
// })
// // 开始爬取 url
// err := c.Visit(url)
// if err != nil {
// fmt.Println(err)
// }
}
// 翻页
func (c *Session) NextPage() {
// 访问地址
url := "http://quotes.toscrape.com"
baseUrl := "http://quotes.toscrape.com"
for i := 0; i <= 2; i++ {
fmt.Println("start url: ", url)
// 获取下一页
page, err1 := c.getNext(url)
if err1 != nil {
break
}
url = baseUrl + page
}
}
// 保存
func (c *Session) save(text string, author string, tags []string) {
newTags := strings.Join(tags, " ")
// fmt.Println(newTags)
_, _ = c.file.Write([]byte(text + "\n"))
_, _ = c.file.Write([]byte(author + "\n"))
_, _ = c.file.Write([]byte(newTags + "\n"))
_, _ = c.file.Write([]byte(strings.Repeat("*", 20)))
_, _ = c.file.Write([]byte("\n\n"))
}
func main() {
s := &Session{}
// 初始化
s.Init()
// 读写模式打开,写入追加
s.file, _ = os.OpenFile("test.txt", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0777)
defer func() {
if err := s.file.Close(); err != nil {
fmt.Println(err)
}
}()
// 翻页
s.NextPage()
// 采集等待结束
s.session.Wait()
fmt.Println("程序运行结束!")
}