文章目录

  • 介绍
  • demo

介绍

  • 本章节使用OnResponse进行返回网页数据
  • 使用xpath定位数据;
  • 推荐htmlquery

demo

package mainimport ("fmt""github.com/antchfx/htmlquery""github.com/gocolly/colly""github.com/gocolly/colly/extensions""gopkg.in/xmlpath.v2""log""os""strings""time"
)/*
请求执行之前调用- OnRequest
响应返回之后调用- OnResponse
监听执行 selector- OnHTML
监听执行 selector- OnXML
错误回调- OnError
完成抓取后执行,完成所有工作后执行- OnScraped
取消监听,参数为 selector 字符串- OnHTMLDetach
取消监听,参数为 selector 字符串- OnXMLDetach
*/func init() {// 日志配置// 指定输出日志的前缀log.SetPrefix("【UserCenter】")// Ldate:时间// Lshortfile:文件名+源代码/*const (Ldate         = 1 << iota     //日期示例: 2009/01/23Ltime                         //时间示例: 01:23:23Lmicroseconds                 //毫秒示例: 01:23:23.123123.Llongfile                     //绝对路径和行号: /a/b/c/d.go:23Lshortfile                    //文件和行号: d.go:23.LUTC                          //日期时间转为0时区的LstdFlags     = Ldate | Ltime //Go提供的标准抬头信息)*/log.SetFlags(log.LstdFlags | log.Lshortfile)}// 声明结构体
type Session struct {session *colly.Collectorfile    *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"// 随机UserAgentextensions.RandomUserAgent(c.session)// 限制采集规则/*在Colly里面非常方便控制并发度,只抓取符合某个(些)规则的URLScolly.LimitRule{DomainGlob: "*.douban.*", Parallelism: 5},表示限制只抓取域名是douban(域名后缀和二级域名不限制)的地址,当然还支持正则匹配某些符合的 URLSLimit方法中也限制了并发是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
}// 开始爬取
func (c *Session) Visit(url string) error {// 开始爬取 urlerr := c.session.Visit(url)if err != nil {fmt.Println(err)return err}return nil
}// 访问下一页
// OnHTML selector
func (c *Session) getNext2(page *string) error {// 调用回调函数,获取标签的属性c.session.OnHTML(".pager .next a", func(e *colly.HTMLElement) {// 获取属性值link := e.Attr("href")*page = link})// 错误回调var err1 error = nilc.session.OnError(func(_ *colly.Response, err error) {fmt.Println("Something went wrong:", err)err1 = err})if err1 != nil {fmt.Println(err1)return err1}// 完成抓取后执行,完成所有工作后执行// c.session.OnScraped(func(r *colly.Response) {//     fmt.Println("Finished", r.Request.URL)// })return nil
}// htmlquery xpath 推荐
func (c *Session) getNext(page *string) error {// 完成抓取后执行,完成所有工作后执行// c.session.OnScraped(func(r *colly.Response) {//    fmt.Println("Finished", r.Request.URL)// })// 收到响应后c.session.OnResponse(func(r *colly.Response) {doc, err := htmlquery.Parse(strings.NewReader(string(r.Body)))if err != nil {log.Fatal(err)}link := htmlquery.FindOne(doc, `//ul[@class="pager"]/li[@class="next"]/a/@href`)*page = htmlquery.InnerText(link)// fmt.Println(*page)})// 错误回调var err1 error = nilc.session.OnError(func(_ *colly.Response, err error) {fmt.Println("Something went wrong:", err)err1 = err})if err1 != nil {fmt.Println(err1)return err1}return nil
}// gopkg.in/xmlpath.v2 xpath
func (c *Session) getNext3(page *string) error {// 完成抓取后执行,完成所有工作后执行// c.session.OnScraped(func(r *colly.Response) {//   fmt.Println("Finished", r.Request.URL)// })// 收到响应后c.session.OnResponse(func(r *colly.Response) {doc, err := xmlpath.ParseHTML(strings.NewReader(string(r.Body)))if err != nil {log.Fatal(err)}path := xmlpath.MustCompile(`//ul[@class="pager"]/li[@class="next"]/a/@href`)if link, ok := path.String(doc); ok {*page = link}})// 错误回调var err1 error = nilc.session.OnError(func(_ *colly.Response, err error) {fmt.Println("Something went wrong:", err)err1 = err})if err1 != nil {fmt.Println(err1)return err1}return nil
}// 解析页面 OnHTML
func (c *Session) getParse2() {// 在每个 a 标签 href 属性 调用回调函数c.session.OnHTML(".row .col-md-8 .quote", func(e *colly.HTMLElement) {// texttext := e.ChildText("span.text")// fmt.Println("text: ", text)// authorauthor := e.ChildText("span .author")// fmt.Println("author: ", author)// tagsvar tags []stringe.ForEach(".tags a", func(i int, e *colly.HTMLElement) {text := e.Texttags = append(tags, text)})// fmt.Println("tags: ", tags)// 保存c.save(text, author, tags)})// 收到响应后c.session.OnResponse(func(r *colly.Response) {if r.StatusCode != 200 {log.Println(r.StatusCode)return}})
}// 解析页面 htmlquery xpath
func (c *Session) getParse() {// 收到响应后c.session.OnResponse(func(r *colly.Response) {if r.StatusCode != 200 {log.Println(r.StatusCode)return}doc, err := htmlquery.Parse(strings.NewReader(string(r.Body)))if err != nil {log.Fatal(err)}quoteNodes := htmlquery.Find(doc, `//div[@class="row"]/div[@class="col-md-8"]/div[@class="quote"]`)for _, node := range quoteNodes {textNode := htmlquery.FindOne(node, `./span[@class="text"]/text()`)text := htmlquery.InnerText(textNode)authorNode := htmlquery.FindOne(node, `./span/small[@class="author"]/text()`)author := htmlquery.InnerText(authorNode)var tags []stringaNodes := htmlquery.Find(node, `./div[@class="tags"]/a`)for _, a := range aNodes {tagNode := htmlquery.FindOne(a, `./text()`)tag := htmlquery.InnerText(tagNode)tags = append(tags, tag)}fmt.Println(text)fmt.Println(author)fmt.Println(tags)// 保存c.save(text, author, tags)}})
}// 翻页
func (c *Session) NextPage() {// 访问地址url := "http://quotes.toscrape.com"baseUrl := "http://quotes.toscrape.com"page := ""for i := 0; i <= 2; i++ {fmt.Println("start url: ", url)// 解析页面c.getParse()// 获取下一页地址err1 := c.getNext(&page)if err1 != nil {break}err2 := c.Visit(url)if err2 != 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("程序运行结束!")
}

gocolly-OnResponse的使用(3)相关推荐

  1. (golang)HTTP基本认证机制及使用gocolly登录爬取

    内网有个网页用了HTTP基本认证机制,想用gocolly爬取,不知道怎么登录,只好研究HTTP基本认证机制 参考这里:https://www.jb51.net/article/89070.htm 下面 ...

  2. Golang 网络爬虫框架gocolly/colly

    gocolly是Golang实现的网络爬虫框架,名列go版爬虫程序榜首. 安装 go get -u github.com/gocolly/colly/... 例子 import ( "fmt ...

  3. 非零基础自学Golang 第17章 HTTP编程(上) 17.3 爬虫框架gocolly 17.3.1 gocolly简介

    非零基础自学Golang 文章目录 非零基础自学Golang 第17章 HTTP编程(上) 17.3 爬虫框架gocolly 17.3.1 gocolly简介 第17章 HTTP编程(上) 17.3 ...

  4. Golang 网络爬虫框架gocolly/colly 四

    爬虫靠演技,表演得越像浏览器,抓取数据越容易,这是我多年爬虫经验的感悟.回顾下个人的爬虫经历,共分三个阶段:第一阶段,09年左右开始接触爬虫,那时由于项目需要,要访问各大国际社交网站,Facebook ...

  5. go-colly入门+案例

    我们可以先在文档先了解一下 go-colly c.OnRequest(func(r *colly.Request) {fmt.Println("Visiting", r.URL) ...

  6. go-colly官方文档翻译(持续翻译中)

    介绍 如何安装 煤灰只有一个前提,那就是Golang编程语言. 你可以使用他们的安装指南 https://golang.org/doc/install 在终端输入以下命令安装煤灰和回车. go get ...

  7. Golang网络爬虫框架gocolly/colly(三)

    熟悉了<Golang 网络爬虫框架gocolly/colly 一>和<Golang 网络爬虫框架gocolly/colly 二>之后就可以在网络上爬取大部分数据了.本文接下来将 ...

  8. 安装 Go-Colly

    1.go get -u github.com/gocolly/colly/ 2.执行完后看到如下报错 package github.com/gocolly/colly imports golang.o ...

  9. go 爬虫框架 - gocolly

    colly 是 Go 实现的比较有名的一款爬虫框架,而且 Go 在高并发和分布式场景的优势也正是爬虫技术所需要的.它的主要特点是轻量.快速,设计非常优雅,并且分布式的支持也非常简单,易于扩展. 使用 ...

  10. Android --- Retrofit 之 Okhttp3 网络请求总是调用 onFailure 方法,而不调用 onResponse,报错 timeout。

    今天在做 Android 项目的时候使用到了 okhttp3 的网络请求,由于我没有设置 ReadTimeout,指的是建立连接后从服务器读取到可用资源所用的时间.所以就会抛出异常(timeout), ...

最新文章

  1. 失业后跑摩的985高校硕士,被质疑学历、深“扒”论文...
  2. Mysql高级调优篇——前言简介
  3. 安装mysql5.7出现问题_转载---安装mysql5.7,遇到的问题
  4. iOS开发基础知识-多线程概念深入浅出
  5. 最长上升子序列(LIS)和最长公共子序列(LCS) 模板
  6. linux查看yum源信息,Linux系统配置163或sohu yum源
  7. (转)比较全的OA模板
  8. Detours使用方法,简单明了
  9. 第八章-分析句子结构
  10. golang库文件收集
  11. Allegro导出pdf的两种方式
  12. 技嘉显卡性能测试软件,显卡性能与超频:性能高于公版,超频潜力可圈可点
  13. 字符串函数的模拟实现
  14. 算法实践——数独的基本解法
  15. 实测搭建学法减分助手小程序系统源码
  16. 8.14. JSON Types
  17. 快速保存网页中所有图片的方法
  18. 【杂谈】 Listary自带的字典功能失效?没关系,让我们自己来改造它
  19. 2016计算机学科夏令营上机考试C:反反复复(字符串处理)
  20. 反弹Shell命令一键生成工具

热门文章

  1. AppCompat 22 1 Google暴走,MD全面兼容低版本
  2. 一级域名,二级域名,父域名,子域名之间的联系
  3. vue中修改props传进来的值
  4. linux上安装Ubuntu (在苹果笔记本上用了移动硬盘装的)
  5. 改default client等小技巧
  6. Thiol-PEG-SH,巯基聚乙二醇巯基,Thiol-PEG-Thiol
  7. 对于tomcat升级导致游览器访问页面出现的中文乱码问题解决方案
  8. NodeMcu开发环境配置Arduino IDE
  9. Oracle分析函数使用总结
  10. 孟凯:卖菜的难道一定要终身卖菜吗?