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/")
}
文章来源:https://www.toymoban.com/news/detail-511565.html
到了这里,关于Golang爬虫学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!