Golang爬虫学习

这篇具有很好参考价值的文章主要介绍了Golang爬虫学习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

2023年将会持续于B站、CSDN等各大平台更新,可加入粉丝群与博主交流:838681355,为了老板大G共同努力。
【商务合作请私信或进群联系群主】文章来源地址https://www.toymoban.com/news/detail-511565.html

一、golang-net/http包(正则)

1.1 简介和示例

导包:
import(
    "fmt"
    "io/ioutil"
    "net/http"
)

创建请求:
	client := &http.Client{} 
	req,_ := http.NewRequest("GET",url,nil)
示例:
import (
	"fmt"
	"io/ioutil"
	"net/http"
)
func pachong(url string) string{ // 设置一个变量名为Url,类型为string
	// Get请求服务
	client := &http.Client{} 
	req,_ := http.NewRequest("GET",url,nil)
	// 设置ua头,cookie等,是为了绕过一些爬虫机制
	req.Header.Set("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0")
	req.Header.Add("Cookie","buvid3=65BAA442-C9DA-443F-9A21-DD07C777480C34756infoc;")
	// 请求处理
	resp,err := client.Do(req)
	if err != nil{
		fmt.Println("Http get err:",err)
		return ""
	}
	if resp.StatusCode != 200{
		fmt.Println("Htpp status code:",resp.StatusCode)
		return ""
	}
	// 处理完毕后关掉连接
	defer resp.Body.Close() 
	body,err := ioutil.ReadAll(resp.Body)
	if err != nil{
		fmt.Println("Read error",err)
		return ""
	}
	return string(body)
}
func main(){
	url := "https://www.baidu.com" //付给变量url地址
	s := pachong(url) //用方法引用该变量url,付给s
	fmt.Printf(s) // 打印输出
}

1.2 爬虫解析页面

导包:
import(
    "fmt"
    "io/ioutil"
    "net/http"
    "regexp"
    "strings"
)

如何解析到想要的数据:
1.替换空格,去除空格
2.找到标签,找到页面内容`<div class="article">(.*?)</div>`
3.找到标题(`<h1 class="article-title" itemprop="name">(.*?)</h1>`)
4.找到页面内容
5.切片
1.2.1 解析链接页面
func parse(html string){ // 解析链接页面,主要采用正则表达式
	// 替换掉空格
	html = strings.Replace(html,"\n","",-1)
	// 边栏内容正则
	re_sidebar := regexp.MustCompile(`<aside id="sidebar" role="navigation">(.*?)</aside>`) // (.*?)任意匹配
	// 找到边栏内容块
	sidebar := re_sidebar.FindString(html) // 意思是在html里头找re_sidebar正则匹配的内容
	// 链接正则
	re_link := regexp.MustCompile(`href="(.*?)"`)
	// 找到所有链接
	links := re_link.FindAllString(sidebar,-1)

	base_url := "https://gorm.io/zh_CN/docs/"
	for _, v := range links{
		fmt.Printf("v: %v\n", v)
		s := v[6:len(v)-1] // 抓取到的切片取从第六位开始,到最后一位减一,href="index.html"
		url := base_url + s
		fmt.Printf("url:%v\n",url) // 做字符串链接
	}
}
1.2.2 解析内容页面
func parse2(body string){
		// 替换掉空格
		body = strings.Replace(body,"\n","",-1)
		// 内容正则
		re_content := regexp.MustCompile(`<div class="article">(.*?)</div>`) // (.*?)任意匹配
		// 找到页面内容
		content := re_content.FindString(body) // 意思是body里头找re_sidebar正则匹配的内容
		// 标题
		re_title := regexp.MustCompile(`<h1 class="article-title" itemprop="name">(.*?)</h1>`)
		// 找到页面内容
		title := re_title.FindString(content)
		fmt.Printf("title: %v\n", title)
		// 切片
		title = title[42 : len(title)-5]
		fmt.Printf("title: %v\n", title)
}
1.2.3 代码实例
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp" // 正则标准库
	"strings"
)
func pachong(url string) string{ // 设置一个变量名为Url,类型为string
	// Get请求服务
	client := &http.Client{} 
	req,_ := http.NewRequest("GET",url,nil)
	// 设置ua头,cookie等,是为了绕过一些爬虫机制
	req.Header.Set("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0")
	req.Header.Add("Cookie","buvid3=65BAA442-C9DA-443F-9A21-DD07C777480C34756infoc; CURRENT_FNVAL=4048; PVID=1; CURRENT_QUALITY=0; blackside_state=0; fingerprint=d51052e7d692cb696b50a17a3078c108; buvid_fp=2a41143fc6b7358421c5668cd60fe1cb; LIVE_BUVID=AUTO9116241867606956; b_ut=5; i-wanna-go-back=-1; CURRENT_BLACKGAP=0; buvid4=57E262C3-373B-0C43-11A2-EFB150BEE9EC87880-022012716-c8mC4VtaIp9z9jT1JvXl9w%3D%3D; nostalgia_conf=-1; bp_video_offset_494577303=746190708927365100; hit-dyn-v2=1; _uuid=2F10DDA24-1772-D10C4-8D76-B108D105E7E78981241infoc; buvid_fp_plain=undefined; fingerprint3=4ac7728b721e19742b1f93d7585c875d; b_nut=100; sid=5axxdv1c; SESSDATA=da784f22%2C1680100070%2C110b4%2A91; bili_jct=9e665d59c5d2c8f6fddecad47c65e920; DedeUserID=494577303; DedeUserID__ckMd5=92cd12f6622dfb59; rpdid=|(JYYRlYR))u0J'uYY)~~lJ|R; innersign=1; b_lsid=EB4EB6E9_1857603661D; theme_style=ligh")
	// 请求处理
	resp,err := client.Do(req)
	if err != nil{
		fmt.Println("Http get err:",err)
		return ""
	}
	if resp.StatusCode != 200{
		fmt.Println("Htpp status code:",resp.StatusCode)
		return ""
	}
	// 处理完毕后关掉连接
	defer resp.Body.Close() 
	body,err := ioutil.ReadAll(resp.Body)
	if err != nil{
		fmt.Println("Read error",err)
		return ""
	}
	return string(body)
}
func parse(html string){ // 解析链接页面,主要采用正则表达式
	// 替换掉空格
	html = strings.Replace(html,"\n","",-1)
	// 边栏内容正则
	re_sidebar := regexp.MustCompile(`<aside id="sidebar" role="navigation">(.*?)</aside>`) // (.*?)任意匹配
	// 找到边栏内容块
	sidebar := re_sidebar.FindString(html) // 意思是在html里头找re_sidebar正则匹配的内容
	// 链接正则
	re_link := regexp.MustCompile(`href="(.*?)"`)
	// 找到所有链接
	links := re_link.FindAllString(sidebar,-1)

	base_url := "https://gorm.io/zh_CN/docs/"
	for _, v := range links{
		fmt.Printf("v: %v\n", v)
		s := v[6:len(v)-1] // 抓取到的切片取从第六位开始,到最后一位减一,href="index.html"
		url := base_url + s
		fmt.Printf("url:%v\n",url) // 做字符串链接
		
		body := pachong(url)
		go parse2(body) // 启动另外一个线程处理
	}
}
func parse2(body string){
		// 替换掉空格
		body = strings.Replace(body,"\n","",-1)
		// 内容正则
		re_content := regexp.MustCompile(`<div class="article">(.*?)</div>`) // (.*?)任意匹配
		// 找到页面内容
		content := re_content.FindString(body) // 意思是body里头找re_sidebar正则匹配的内容
		// 标题
		re_title := regexp.MustCompile(`<h1 class="article-title" itemprop="name">(.*?)</h1>`)
		// 找到页面内容
		title := re_title.FindString(content)
		fmt.Printf("title: %v\n", title)
		// 切片
		title = title[42 : len(title)-5]
		fmt.Printf("title: %v\n", title)
}
func main(){
	url := "https://gorm.io/zh_CN/docs" //付给变量url地址
	s := pachong(url) //用方法引用该变量url,付给s
	//fmt.Printf(s) // 打印输出
	parse(s)
}

1.3 保存至文件

func save(title string,content string){
    err := os.WriteFile("./"+title+".html",[]byte(content),0644)
    if err != nil{
        panic(err)
    }
}

1.4 保存至数据库

安装库:
go get xorm.io/xorm
go get github.com/go-sql-driver/mysql

导包:
import(
    "fmt"
    "io/ioutil"
    "net/http"
    "regexp"
    "strings"
    "xorm.io/xorm"
    "github.com/go-sql-driver/mysql"
)

连接数据库:
var engine *xorm.Engine
var err error

func init(){
    engine,err = xorm.NewEngine("mysql","root:123456@/test_xorm?charset=utf8")
    if err != nil{
        fmt.Printf("err:%v\n",err)
    }else{
        err2 := engine.Ping()
        if err2 != nil{
            fmt.Printf("err2:%v\n",err2)
        }else{
            print("连接成功!")
        }
    }
}

创建结构体:
type GormPage struct{
    Id int64
    Title string
    Content string `xorm:"text"`
    Created time.Time `xorm:"created"`
    Updated time.Time `xorm:"updated"`
}

保存数据到数据库:
func saveToDB(title string,content string){
    engine.Sync(new(GormPage)) // 创建的数据库表名为gorm_page
    page := GormPage{
        Title:title,
        Content:content,
    }
    affected,err := engine.Insert(&page)
    if err != nil{
        fmt.Printf("err:%v\n",err)
    }
    fmt.Println("save:"+string(affected))
}
解析内容中加入:saveToDB(title,content)

二、golang-goquery

goquery是一个爬虫库,可以非常方便进行html页面分析,元素提取,类似jquery,它基于html解析库net/html和css库cascadia,提供与jquery相近的接口,go著名的爬虫框架colly就是基于goquery。

安装:go get -u github.com/PuerkitoBio/goquery

2.1 爬取示例

package main

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
)
func main() {
	url := "https://gorm.io/zh_CN/docs" //付给变量url地址
	d, _ := goquery.NewDocument(url)
	d.Find(".sidebar-link").Each(func(i int, s *goquery.Selection) { //查找class里面的包含sidebar-link所有的元素
		s2 := s.Text()
		fmt.Printf("s2:%v\n", s2)
		href, _ := s.Attr("href") // 在class大类中找到href属性,将链接爬取
		fmt.Printf("href:%v\n", href)
	})
}

2.2 Goquery Api Document

Document表示要爬取的文档。

方式一:goquery.NewDocument(url)
	url := "https://gorm.io/zh_CN/docs" //付给变量url地址
	dom , err := goquery.NewDocument(url) // 加载文档
	if err != nil{
		log.Fatalln(err)
	}

方式二:goquery.NewDocumentFromResponse(resp)
	client := &http.Client{} // 打开连接
	url := "https://gorm.io/zh_CN/docs" //付给变量url地址
	req,_ := http.NewRequest("GET",url,nil) // 连接方式GET,传递url
	resp,err := client.Do(req)
	dom,err := goquery.NewDocumentFromResponse(resp)
	if err != nil{
		log.Fatalln(err)
	}
    dom.Find() //爬虫过程

方式三:goquery.NewDocumentFromReader(strings.NewReader(html))
    func main() {
        html := `<body>
                      <div>DIV1</div>
                      <div>DIV2</div>
                      <span>SPAN</span>
                 </body>`
        dom, err := goquery.NewDocumentFromReader(strings.NewReader(html)) //本地读取html方式
        if err != nil {
            log.Fatalln(err)
        }
        dom.Find("")
    }
2.2.1 Goquery Api 选择器
Goquery选择器:类似jQuery或css选择器,常用的有元素名称选择器、ID选择器、class选择器

元素名称选择器:
func main() {
	html := `<body>
                  <div>DIV1</div>
                  <div>DIV2</div>
                  <span>SPAN</span>
             </body>`
	dom, err := goquery.NewDocumentFromReader(strings.NewReader(html))
	if err != nil {
		log.Fatalln(err)
	}
	dom.Find("div").Each(func(i int, selection *goquery.Selection) { //选择div标签,匹配所有
		fmt.Println("i", i, "select text", selection.Text())
	})
}

ID选择器:
func main() {
	html := `<body>
                  <div id="div1">DIV1</div> // 变成div id="div1"
                  <div>DIV2</div>
                  <span>SPAN</span>
             </body>`
	dom, err := goquery.NewDocumentFromReader(strings.NewReader(html))
	if err != nil {
		log.Fatalln(err)
	}
	dom.Find("#div1").Each(func(i int, selection *goquery.Selection) { // 匹配div1
		fmt.Println("i", i, "select text", selection.Text())
	})
}

class选择器:
func main() {
	html := `<body>
                  <div id="div1">DIV1</div>
                  <div class="name">DIV2</div>
                  <span>SPAN</span>
             </body>`
	dom, err := goquery.NewDocumentFromReader(strings.NewReader(html))
	if err != nil {
		log.Fatalln(err)
	}
	dom.Find(".name").Each(func(i int, selection *goquery.Selection) { // 匹配class中的name
		fmt.Println("i", i, "select text", selection.Text())
	})
}

2.3 Goquery Api Selection

select可以提取、删除、添加元素、属性内容

内容函数:
1) 类似函数的位置操作
Eq(index int) *Selection // 根据索引获取某个节点集
First() *Selection // 获取第一个子节点集
Last() *Selection // 获取最后一个子节点集
Next() *Selection // 获取下一个兄弟节点集
NextAll() *Selection // 获取后面所有兄弟节点集
Prev() *Selection // 前一个兄弟节点集
Get(index int) *html.Node // 根据索引获取一个节点
Index() int // 返回选择对象中第一个元素的位置
Slice(start,end int) *Selection // 根据起始位置获取子节点集

2) 循环遍历选择的节点
Each(f func(int, *Selection)) *Selection //遍历
EachWithBreak(f func(int,*Selection)bool) *Selection //可中断遍历
Map(f func(int,*Selection)string)(result []string) //返回字符串数组

3) 检测或获取节点属性值
Attr(),RemoveAttr(),SetAttr() //获取,移除,设置属性的值
AddClass(),HasClass(),RemoveClass(),ToggleClass()
Html() // 获取该节点的Html
Length() //返回该Selection的元素个数
Text() //获取该节点的文本值

4) 在文档书之间来回跳转(常用的查找节点方法)
Children() //返回Selection中各个节点下的孩子节点
Contents() //获取当前节点下的所有节点
Find() //查找获取当前匹配的元素
Next() //下一个元素
Prev() //上一个元素

三、爬虫框架-colly

Colly是go语言编写的Web框架,提供一个能够写任何爬虫、采集器、蜘蛛的简洁模板。

特性:
1.API清晰
2.速度快
3.管理每个域的请求延迟和最大并发数
4.自动cookie会话处理
5.同步、异步、并行抓取
6.高速缓存
7.自动处理非unicode编码
8.支持Robots.txt
9.支持google APP engine
10.通过环境变量进行配置
11.可拓展

安装:go get -u github.com/gocolly/colly

3.1 爬取示例

import (
	"fmt"
	"github.com/gocolly/colly"
)

func main() {
	c := colly.NewCollector()
	c.OnHTML(".siderbar-link", func(e *colly.HTMLElement) {
		e.Request.Visit(e.Attr("href"))
	})
	c.OnRequest(func(r *colly.Request) {
		fmt.Println("url", r.URL)
	})
	c.Visit("https://xxx/) // 爬取的URL
}

3.2 回调方法

请求之前调用:OnRequest
请求期间发生错误调用:OnError
收到响应标头后调用:OnResponseHeaders
收到响应后调用:OnResponse
OnResponse接收的内容HTML就调用:OnHTML
OnHTML接收内容是HTML或XML就调用:OnXML
回调后OnXML调用:OnScraped

示例:
    c := colly.NewCollector()
    c.OnRequest(func(r *colly.Request) {
        fmt.Println("请求前调用:OnRequest")
    })
    c.OnError(func(_*colly.Response, err error) {
        fmt.PrintIn("发生错误调用:OnError")
    })
    c.OnResponse(func(r *colly.Response) {
        fmt.PrintIn("获得响应后调用:OnResponse")
    })
    c.OnHTML("a[href]"func(e *colly.HTMLElement) {
        fmt.PrintIn("OnResponse接收的内容HTML就调用:OnHTML")
    c.OnXML("//h1"func(e *colly.XMLElement) {
        fmt.PrintIn("onResponse收到xm1内容后调用:OnXML")
    })
    c.OnScraped(func(r *colly.Response) {
        fmt.Println("结束",r.Request.URL)
    })

3.3 配置

设置UserAgent:
    c := colly.NewCollector()
    c.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0"

设置cookie:
方式一:
    c.OnRequest(func(r *colly.Request){
        r.Headers.Add("cookie","")
    })
方式二:
    siteCokkie := C.Cookies("url")
    c.SetCookies("",siteCokkie)

HTTP配置:
    c := colly.NewCollectior()
    c.WithTransport(&http.Transport{
        Proxy:http.ProxyFromEnvironment,
        DialContext:(&net.Dialer{
            Timeout: 30 * time.Second,
            KeepAlive: 30 * time.Second,
            DualStack: true,
        }).DialContext,
        MaxIdleConns: 100,
        IdleConnTimeout: 90 * time.Second,
        TLSHandshakeTimeout: 10 * time.Second,
        ExpectContinueTimeout: 1 * time.Second,
    })

3.4 页面爬取和解析

页面爬取和解析重点方法是OnHTML的回调方法
    c.OnHTML("a[href]",func(e *colly.HTMLElement){
        e.Request.Visit(e.Attr("href"))
    })

3.5 框架重构爬虫应用

import (
	"fmt"
	"github.com/gocolly/colly"
)

func main() {
	c := colly.NewCollector()
	c.OnHTML(".sidebar-link", func(e *colly.HTMLElement) {
		href := e.Attr("href")
		if href != "index.html" { // 如果等于index.html则继续访问
			c.Visit(e.Request.AbsoluteURL(href))
		}
	})
	c.OnHTML(".article-title", func(h *colly.HTMLElement) { // 跳转链接后,找到ariticle-title,获取他的内容
		content, _ := h.DOM.Html()
		fmt.Printf("content:%v\n", content)
	})
	c.OnHTML(".article", func(h *colly.HTMLElement) {
		content, _ := h.DOM.Html()
		fmt.Printf("content:%v\n", content)
	})
	c.OnRequest(func(r *colly.Request) {
		fmt.Println("Visiting", r.URL.String())
	})
	c.Visit("https://gorm.io/zh_CN/docs/")
}

到了这里,关于Golang爬虫学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深度学习面试八股文(2023.9.06持续更新)

    一、优化器 1、SGD是什么? 批梯度下降(Batch gradient descent):遍历全部数据集算一次损失函数,计算量开销大,计算速度慢,不支持在线学习。 随机梯度下降(Stochastic gradient descent,SGD) 每次随机选择一个数据计算损失函数,求梯度并更新参数,计算速度快,但收敛性能可

    2024年02月09日
    浏览(40)
  • .net平台使用SDK快速对接各大语言模型

    最近,在做GPT项目时,发现各个平台的接口规范和参数不同,需要根据不同平台和模型写多种接口,比较麻烦,不想Python那样有丰富和方便的AI环境, 如果c#有一个SDK可以方便调用各种平台模型就好了,这是AllInAI.Sharp.API萌芽的起源。 于是我开发了这个SDK,包名:[AllInAI.Shar

    2024年02月05日
    浏览(48)
  • 新手小白如何自学制作电子画册并分享各大平台

    一提到电子画册制作,相信很多人都开始头大了,毕竟对于新手小白来说还是比较难的,那么,新手小白要如何自学制作电子画册并快速分享出去呢,其实只需要一个在线电子画册制作平台FLBOOK就可以了 。 小白该怎样制作电子画册呢? 1.画册定位: 首先要确定画册的主题以

    2024年02月06日
    浏览(34)
  • 江科大STM32学习笔记(详细版)——2023持续更新

    基础篇 是到时候我自己找其它视频补充(就比如寄存器影射,时钟树),到时候写在其它文章里。 主篇(外设篇)目前是跟着@江协科技的STM32入门教程-2023版 细致讲解 中文字幕视频来学习的,大家可以边看视频边根据我的笔记做适合自己的笔记; 另外,因为篇幅太长了,我将

    2024年02月06日
    浏览(44)
  • SpiderFlow爬虫平台(爬虫学习)

    作为自己学习的记录,方面后期查阅 SpiderFlow官网 spider-flow 是一个爬虫平台,以图形化方式定义爬虫流程,无需代码即可实现一个爬虫 是使用springboot开发的项目,后端代码直接运行即可使用

    2024年02月15日
    浏览(31)
  • python3 爬虫相关学习8:python 的常见报错内容汇总(持续收集ing)

    目录 1 低级错误(比如拼写错误等)  1.1 NameError:  1.2 属性错误 AttributeError:  属性拼写错误 2  应用错误(类型应用,属性使用的错误) 2.1 类型错误 TypeError:  如字符串连接错误 2.2  属性应用错误  AttributeError 3 模块相关错误 3.1 找不到对应模块 ModuleNotFoundError: 3.2 相关模

    2024年02月04日
    浏览(41)
  • 算法面试-深度学习基础面试题整理-AIGC相关(2023.9.01开始,持续更新...)

    1、stable diffusion和GAN哪个好?为什么 ? Stable diffusion是一种基于随机微分方程的生成方法,它通过逐步增加噪声来扰动原始图像,直到完全随机化。然后,它通过逐步减少噪声来恢复图像,同时使用一个神经网络来预测下一步的噪声分布。Stable Diffusion的优点是可以在连续的潜

    2024年02月10日
    浏览(47)
  • 2023爬虫学习笔记 -- selenium反爬虫操作(window.navigator.webdriver属性值)

    一、无可视化浏览器操作 1、导入需要的函数,固定写法,并设置相关浏览器参数 2、请求的时候加上参数设置 3、通过截图证明确实被打开了 二、有些网站通过判断window.navigator.webdriver属性值来判断是否有爬虫行为 1、正常访问浏览器,该属性值为false 2、通过webdriver访问浏览

    2024年02月08日
    浏览(39)
  • ChatGPT将会成为强者的外挂?—— 提高学习能力

    目录 前言 一、提高学习力 🧑‍💻 1. 快速找到需要的知识 2. 组合自己的知识体系 3. 内化知识技能 二、提问能力❗ 三、思维、创新能力 🌟 1. 批判性思维 1.1 八大基本结构进行批判性提问 1.2 苏格拉底的提问分类方法 2. 结构化思维 3. 创新思维 总结           在上篇我已

    2024年02月13日
    浏览(35)
  • 2023.8各大浏览器11家对比:Edge/Chrome/Opera/Firefox/Tor/Vivaldi/Brave,安全性,速度,体积,内存占用

    测试环境:全默认设置的情况下,均在全新的系统上进行测试,系统并未进行任何改动,没有杀毒软件,浏览器进程全部在后台,且为小窗模式,小窗分辨率均为浏览器厂商默认缩放大小(变量不唯一),浏览器中没有网页,均在新标签页停留,表格列出均为默认设置,排除插

    2024年02月11日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包