公众号平台怎么做,南昌seo关键词,广告网站设计方案,博客论坛用wordpress我的Go语言初体验——#xff08;4#xff09;零基础学习 Go 爬虫
“我的Go语言初体验” | 征文活动进行中… Go 语言非常适合编写爬虫程序#xff0c;具有并发机制完善、并发数量大、占用资源少、运行速度快、部署方便的优点。 本文结合官方文档与 Go 语言的资料#xff…我的Go语言初体验——4零基础学习 Go 爬虫
“我的Go语言初体验” | 征文活动进行中… Go 语言非常适合编写爬虫程序具有并发机制完善、并发数量大、占用资源少、运行速度快、部署方便的优点。 本文结合官方文档与 Go 语言的资料循序渐进介绍 Go 爬虫编程通过多个完整例程带你学习和编写爬虫程序。 本文全部例程已在 Go 环境下进行了测试。 1. 为什么用 Go 语言编写爬虫
网络爬虫的工作原理是通过检查 web 页面的 HTML 内容并基于内容执行某种类型的行动。特别是提取当前页面的数据以及通过抓取和分析暴露的链接按照队列去爬取页面数据。
Go 语言非常适合编写爬虫程序并且具有独特的优势
并发机制完善并发数量大占用资源少运行速度快部署方便 2. http.Get 方法实现简单请求
2.1 http.Get 方法说明
net 包封装了网络相关的功能最常用的是 http 和 url。Go 语言可以使用 net/http 包实现请求网页。
http.Get 方法的基本语法如下 resp, err : http.Get(“http://example.com/”) 参数请求的目标 URL 向服务器发送一个 http get 请求得到 response。
2.2 http.Get 获得网页的 html 源文件
我们首先用 http.Get 编写一个简单的爬虫程序。
【例程 1】http.Get 获得网页的 html 源文件
// 1. http.Get 获得网页的 html 源文件
package main
import (fmtio/ioutilnet/http
)func main() {resp, _ : http.Get(http://www.baidu.com)defer resp1.Body.Close()contents, _ : ioutil.ReadAll(resp.Body)fmt.Println(string(contents))
}运行【例程1】可以抓取百度首页的 html 源文件。
数据太多看不清楚没有关系我们可以把抓取的数据保存下来。 2.3 异常处理和网页保存
网络活动十分复杂对网站的访问不一定都会成功因此需要对爬取过程中的异常进行处理否则爬虫在遇到异常时就会因发生运行错误。
导致异常的原因主要有
链接不上服务器远程URL不存在无网络触发了 HTTPError
我们以 CSDN 热榜网页为例说明异常处理和数据保存并将爬取的网页保存在 .vscode 目录下的 page01.html 文件中。
【例程 2】异常处理和网页保存
// 2. 抓取网页异常处理和数据保存
package main
import (fmtio/ioutilnet/httpos
)func main() {resp, err : http.Get(https://blog.csdn.net/rank/list)if err ! nil {fmt.Printf(%s, err)os.Exit(1)}defer resp.Body.Close()if resp.StatusCode http.StatusOK {fmt.Println(resp.StatusCode)}f, err : os.OpenFile(csdnPage01.html, os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm)if err ! nil {panic(err)return}defer f.Close()buf : make([]byte, 1024)for {n, _ : resp.Body.Read(buf)if 0 n {break}f.WriteString(string(buf[:n]))}
}加入异常处理后可以处理网页访问中发生的异常可以保证从服务器成功获取网页。
但是我们真的抓到了所要的网页吗打开 csdnPage01.html 文件如下图所示。
【例程 2】确实成功抓取了 CSDN 热榜页面中的一些内容但关键的热榜文章的具体内容并没有抓到。没有关系我们一步步来尝试。 3. client.Get 方法实现发起请求
3.1 Client 对象说明
Client 方法是 http 包内部发起请求的组件可以控制请求的超时、重定向和其它设置。
Client 的定义如下
type Client struct {Transport RoundTripper // 超时控制管理CheckRedirect func(req *Request, via []*Request) error // 控制重定向Jar CookieJar // 管理 Cookie 的对象Timeout time.Duration // 限制建立连接的时间
}Client 的简单调用方法与 http.Get 方法类似例如 resp, err : client.Get(“http://example.com”) // 参数请求的目标 URL 3.2 控制 HTTP 客户端的头结构
更加常用地要在请求的时候设置头参数、cookie、证书验证等参数可以在使用 Client 时先构造一个 Request 再调用 Client.Do() 方法。
【例程 3】控制 HTTP 客户端的头结构
// 3. 控制 HTTP 客户端的头结构
package mainimport (encoding/jsonfmtio/ioutilnet/httpos
)func checkError(err error) {if err ! nil {fmt.Printf(%s, err)os.Exit(1)}
}func main() {url : https://blog.csdn.net/youcans // 生成 urlclient : http.Client{} // 生成 clientreq, err : http.NewRequest(GET, url, nil) // 提交请求checkError(err) // 异常处理// 自定义Headercookie_str : your cookie // 从浏览器复制的 cookie 字符串req.Header.Set(Cookie, cookie_str)userAgent_str : Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)req.Header.Set(User-Agent, userAgent_str) // 生成 User-Agentresp, err : client.Do(req) // 处理返回结果checkError(err)defer resp.Body.Close() // 关闭相关链接// 状态码检验 (http.StatusOK200)if resp.StatusCode http.StatusOK {fmt.Println(resp.StatusCode)}/*contents, err : ioutil.ReadAll(resp.Body)checkError(err)fmt.Println(string(contents))*/f, err : os.OpenFile(csdnPage02.html, os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm)if err ! nil {panic(err)return}defer f.Close()buf : make([]byte, 1024)for {n, _ : resp.Body.Read(buf)if 0 n {break}f.WriteString(string(buf[:n]))}
}【例程 3】成功抓取了 CSDN 网站的 youcans 页面。打开 csdnPage01.html 文件显示如下 3.3 解析网页数据
对于获取的网页源代码需要进行解析以得到我们需要的数据。
依据响应的不同类型可以选择不同的方法: 对于 html 格式的数据可以选择正则表达式或者 Css 选择器获取所需的内容 对于 json 格式的数据可以使用 encoding/json 库对获取的数据反序列化获取所需的内容。
正则表达式是进行模式匹配和文本操纵的的工具。Go 语言通过 regexp 包为正则表达式提供支持采用 RE2 语法与 Go、Python 语言的正则一致。
【函数说明】func MustCompile(str string) *Regexp 通过 MustCompile 可以创建一个 Regexp 对象 MustCompile 用来解析正则表达式 str 是否合法 如果合法则返回一个 Regexp 对象如果不合法则抛出异常 例如
rp :regexp.MustCompile(div classhd(.*?)/div)
// 查找并返回以 div classhd 开头以 /div 结尾的字符串
titleRe : regexp.MustCompile(span classtitle(.*?)/span)
// 查找并返回以 span classtitle 开头以 /span 结尾的字符串**【函数说明】func (re *Regexp) FindAllStringSubmatch(s string, n int) string ** 在 s 中查找 re 中编译好的正则表达式并返回所有匹配的内容 同时返回子表达式匹配的内容 **【函数说明】func (re *Regexp) FindStringSubmatchIndex(s string) []int ** 在 s 中查找 re 中编译好的正则表达式并返回第一个匹配的位置 同时返回子表达式匹配的位置 【函数说明】func (re *Regexp) FindStringSubmatch(s string) []string 在 s 中查找 re 中编译好的正则表达式并返回第一个匹配的内容 同时返回子表达式匹配的内容 【例程 4】解析网页数据
// 4. 解析网页数据
package main
import (fmtio/ioutilnet/httposregexpstrconvstringstime
)// 异常处理
func checkError(err error) {if err ! nil {fmt.Printf(%s, err)panic(err)}
}// URL 请求
func fetch(url string) string {fmt.Println(Fetch Url, url)client : http.Client{} // 生成 clientreq, err : http.NewRequest(GET, url, nil) // 提交请求checkError(err)// 自定义 HeaderuserAgent_str : Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; http://www.baidu.com)req.Header.Set(User-Agent, userAgent_str) // 生成 User-Agentresp, err : client.Do(req) // 处理返回结果checkError(err)defer resp.Body.Close()// 状态码检验 (http.StatusOK200)if resp.StatusCode 200 {body, err : ioutil.ReadAll(resp.Body) // 读取resp的body内容checkError(err)return string(body)} else {fmt.Printf(%s, err)return }
}// 解析页面
func parseUrls(url string, f *os.File) {//func parseUrls(url string) {body : fetch(url)body strings.Replace(body, \n, , -1) // 去除 body 内容中的回车符rp : regexp.MustCompile(div classhd(.*?)/div)titleRe : regexp.MustCompile(span classtitle(.*?)/span)idRe : regexp.MustCompile(a hrefhttps://movie.douban.com/subject/(\d)/)items : rp.FindAllStringSubmatch(body, -1) // 解析符合正则表达式的结果for _, item : range items {idItem : idRe.FindStringSubmatch(item[1])[1] // 找第一个符合的结果 IDtitleItem : titleRe.FindStringSubmatch(item[1])[1] // 找第一个符合的结果 TITLE//fmt.Println(idItem, titleItem)_, err : f.WriteString(idItem \t titleItem \n)checkError(err)}return
}func main() {f, err : os.Create(topMovie.txt) // 创建文件defer f.Close()_, err f.WriteString(ID\tTitle\n) // 描述字段checkError(err)start : time.Now()// 抓取全部 Top250for i : 0; i 10; i {parseUrls(https://movie.douban.com/top250?startstrconv.Itoa(25*i), f)} // 把数字转成字符串elapsed : time.Since(start)fmt.Printf(Took %s, elapsed)
}【例程 4】中的 URL 请求获取网页数据的程序内容与【例程3】的方法相同只是将其封装为函数 fetch() 以方便使用。
【例程 4】从豆瓣抓取了 Top250 影片的信息运行后控制台显示内容为 Fetch Url https://movie.douban.com/top250?start0 Fetch Url https://movie.douban.com/top250?start25 Fetch Url https://movie.douban.com/top250?start50 Fetch Url https://movie.douban.com/top250?start75 Fetch Url https://movie.douban.com/top250?start100 Fetch Url https://movie.douban.com/top250?start125 Fetch Url https://movie.douban.com/top250?start150 Fetch Url https://movie.douban.com/top250?start175 Fetch Url https://movie.douban.com/top250?start200 Fetch Url https://movie.douban.com/top250?start225 文件 topMovie.txt 保存的内容为 ID Title 1292052 肖申克的救赎 1291546 霸王别姬 1292720 阿甘正传 … 1292528 猜火车 1307394 千年女优 说明【例程4】参考了资深工程师 【Golang编程】的文章用Golang写爬虫(一)特此致谢作者进行了改编并在 Go 环境进行了测试。 3. 总结
Go 语言非常适合编写爬虫程序这也是 Go 的优势领域。
本文结合官方文档与 Go 语言的资料循序渐进介绍 Go 爬虫编程通过多个完整例程带你学习和编写爬虫程序。
本文中的全部例程都已在 Go 环境下进行调试和运行测试。
高并发是 Go 的重要机制和优点在爬虫中也能非常有效我们将在后续文中进行学习。 【本节完】 版权声明
原创作品转载必须标注原文链接(https://blog.csdn.net/youcans/article/details/121644252)
【例程4】参考了资深工程师 “Golang编程”的文章用Golang写爬虫(一)作者进行了改编特此致谢。
Copyright 2021 youcans, XUPT
Crated2021-11-30 欢迎关注『我的Go语言初体验』系列持续更新中… 我的Go语言初体验——1超详细安装教程 我的Go语言初体验——2 IDE 详细安装教程 我的Go语言初体验——3Go 数据类型 我的Go语言初体验——4零基础学习 Go 爬虫 “我的Go语言初体验” | 征文活动进行中…