我的Go+语言初体验——(4)零基础学习 Go+ 爬虫

我的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 ("fmt""io/ioutil""net/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 ("fmt""io/ioutil""net/http""os"
)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/json""fmt""io/ioutil""net/http""os"
)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.StatusOK=200)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 class="hd">(.*?)</div>`)
// 查找并返回以 <div class="hd"> 开头,以 </div> 结尾的字符串
titleRe := regexp.MustCompile(`<span class="title">(.*?)</span>`)
// 查找并返回以 <span class="title"> 开头,以 </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 ("fmt""io/ioutil""net/http""os""regexp""strconv""strings""time"
)// 异常处理
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.StatusOK=200)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 class="hd">(.*?)</div>`)titleRe := regexp.MustCompile(`<span class="title">(.*?)</span>`)idRe := regexp.MustCompile(`<a href="https://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?start="+strconv.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?start=0
Fetch Url https://movie.douban.com/top250?start=25
Fetch Url https://movie.douban.com/top250?start=50
Fetch Url https://movie.douban.com/top250?start=75
Fetch Url https://movie.douban.com/top250?start=100
Fetch Url https://movie.douban.com/top250?start=125
Fetch Url https://movie.douban.com/top250?start=150
Fetch Url https://movie.douban.com/top250?start=175
Fetch Url https://movie.douban.com/top250?start=200
Fetch Url https://movie.douban.com/top250?start=225

文件 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

Crated:2021-11-30


欢迎关注『我的Go+语言初体验』系列,持续更新中…

我的Go+语言初体验——(1)超详细安装教程
我的Go+语言初体验——(2) IDE 详细安装教程
我的Go+语言初体验——(3)Go+ 数据类型
我的Go+语言初体验——(4)零基础学习 Go+ 爬虫

“我的Go+语言初体验” | 征文活动进行中…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/565952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

latex的基本使用

LaTeX使用 LaTeX使用基本使用源文件的基本结构中文处理办法字体字号设置文章基本结构特殊字符处理图片的使用表格的使用Texstduio的导入表格功能会更快浮动体的使用数学公式初步矩阵的使用TexStudio里面的矩阵模板功能参考文献使用BibTex定义自己的命令 基本使用 sublime使用…

【OpenCV 例程300篇】48. 直方图处理之彩色直方图匹配

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程300篇】48. 直方图处理之彩色直方图匹配 图像直方图是反映图像像素分布的统计表。 灰度直方图是图像灰度级的函数&#xff0c;用来描述每个灰度级在图像矩阵中的像素个数。 直方图匹配又称为直方图规定化&a…

Vue的安装和配置

Vue是目前最流行的前端框架之一&#xff0c;给大家讲一下如何安装和配置Vue环境。 网上也有许多关于安装和配置Vue的教程&#xff0c;但是他们的方法太过于麻烦了&#xff0c;而且对于初学者来说对网上的一些安装和配置Vue的方法不理解&#xff0c;看了之后还是没有一点思绪&a…

【OpenCV 例程300篇】49. 直方图处理之局部直方图处理(cv2.createCLAHE)

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程300篇】49. 直方图处理之局部直方图处理&#xff08;cv2.createCLAHE&#xff09; 图像直方图是反映图像像素分布的统计表。 灰度直方图是图像灰度级的函数&#xff0c;用来描述每个灰度级在图像矩阵中的像素…

ResNet网络详解与keras实现

ResNet网络详解与keras实现 ResNet网络详解与keras实现Resnet网络的概览Pascal_VOC数据集第一层目录第二层目录第三层目录 梯度退化Residual LearningIdentity vs Projection ShortcutsBottleneck architectureResnet网络构建表ResNet论文结果为了搭建Resnet网络我们使用了以下…

简易计算器

用JavaScript实现简易计算器 先看效果图 计算加法弹框输出计算结果 程序解读&#xff1a; 1.两个输入框和一个下拉框 2. 弹框显示结果 3. 加减乘除的简单运算 代码演示 Html页面内容 <!DOCTYPE html> <html><head><meta charset"utf-8">…

【OpenCV 例程300篇】50. 直方图处理之直方图统计量图像增强

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程300篇】50. 直方图处理之直方图统计量图像增强 图像直方图是反映图像像素分布的统计表。 灰度直方图是图像灰度级的函数&#xff0c;用来描述每个灰度级在图像矩阵中的像素个数。 直方图统计量图像增强&…

在大数据时代下金融风控的分类

Date&#xff1a;2018-05-24 Author&#xff1a;等等 依托城市数据湖海量数据资源&#xff0c;尤其是在信贷领域对企业或者个人的个人信贷画像描述评判准则已经是第三方房贷企业或者银行对借贷人的评分标准。风控建模以数据价值挖掘为导向&#xff0c;吸纳大量数据、人工智能科…

多功能标准型计算器

实现一个标准型计算器及其各项功能的实现 效果图欣赏 是不是看起来很漂亮的呢&#xff1f;&#xff1f;&#xff1f; 功能详解&#xff1a; 屏幕显示输入的数字和符号实现加减乘除运算回退和清零功能小数的运算结果的输出 相信小伙伴们都已经迫不及待的想要知道源码了。 代…

【OpenCV 例程200篇】51. 直方图处理之直方图反向追踪(cv2.calcBackProject)

『youcans 的 OpenCV 例程300篇 - 总目录』 【OpenCV 例程200篇】51. 直方图处理之直方图反向追踪&#xff08;cv2.calcBackProject&#xff09; 图像直方图是反映图像像素分布的统计表。 灰度直方图是图像灰度级的函数&#xff0c;用来描述每个灰度级在图像矩阵中的像素个数。…

【转需】【金融干货】四步教你:开发风控模型?

一、市场调研 目前市面主流的风控模型 1、互联网金融前10名排行榜(数据截止日期2017-09-12) 互联网金融公司排名分别是蚂蚁金服、陆金所、京东金融、苏宁金融、百度金融、腾讯理财通、宜信、钱大掌柜、万达金融和网易理财。 1.1 蚂蚁金服 1.1.1 大数据技术对接第三方征信公司芝…

推箱子

推箱子小游戏原理的实现 功能分析&#xff1a; 1.找一张类似于箱子的图片自行设置图片的大小 2.设置控制箱子移动的四个方向的按钮 3.使用键盘控制图片上下左右的移动、 效果图演示 原始位置 点击键盘向右移动三次向下移动一次后的位置 看了上述过程是不是感觉很有意思呀&…

java web 开发之写在前面(0)

java是sun公司&#xff08;现在属于Oracle公司&#xff09;推出的能够跨越多平台的、可以执行最高的一种面向对象的编程语言&#xff0c;也是目前最先进、特征最丰富、功能最强大的计算机语言。利用java可以编写桌面应用程序&#xff0c;web应用程序、分布式系统、嵌入式系统程…

【OpenCV 例程200篇】52. 图像的相关与卷积运算

【OpenCV 例程200篇】52. 图像的相关与卷积运算 欢迎关注 『OpenCV 例程200篇』 系列&#xff0c;持续更新中 欢迎关注 『Python小白的OpenCV学习课』 系列&#xff0c;持续更新中 滤波通常是指对图像中特定频率的分量进行过滤或抑制。图像滤波是在尽可能保留图像细节特征的条件…

java web 之 网页前端开发基础(1)

1.HTML&#xff08;Hypertext Markup Language&#xff0c;HTML&#xff0c;超文本标记语言&#xff09; 1.1 创建第一个HTML文件 编写html语言可以通过两种方式&#xff0c;一种是手工编写html代码&#xff0c;一种是借助一些开发软件&#xff0c;如Dreamweaver或者微软公司…

文本框为空按钮不可点击

在form表单的提交中判断输入框的内容是否为空&#xff0c;如果输入框的内容为空则按钮不可点击&#xff0c;只有当输入框的内容不为空时才能点击并执行之后的提交等操作。 效果图演示 输入框为空&#xff08;按钮不可点击&#xff0c;点击无效果&#xff09; 输入框不为空时…

【youcans 的 OpenCV 学习课】7. 空间域图像滤波

专栏地址&#xff1a;『youcans 的图像处理学习课』 文章目录&#xff1a;『youcans 的图像处理学习课 - 总目录』 【youcans 的 OpenCV 学习课】7. 空间域图像滤波 图像滤波是在尽可能保留图像细节特征的条件下对目标图像的噪声进行抑制&#xff0c;是常用的图像预处理操作。 …

java web开发之上机指导(2)

创建一个用户注册的页面&#xff0c;让用户输入姓名、密码、电话和邮箱&#xff0c;使用javascript脚本完成密码校验、电话号码校验、邮箱校验和空格内容校验。 开发步骤如下。 &#xff08;1&#xff09;创建一个项目名为CheckInfomation&#xff0c;在WebContent文件夹下创…

小程序开发之基础知识(0)

前言&#xff1a;2016年9月21日,微信小程序正式开启内测。 2017年1月9日0点,万众瞩目的微信第一批小程序正式上线,用户可以体验到各种各样小程序提供的服务。 人类发展史大抵经历了石器时代&#xff0c;青铜器与铁器时代、工业与科技时代&#xff08;从第一次工业革命算起&…

鼠标悬浮改变背景颜色

将鼠标放在div上时div的背景颜色发生改变&#xff0c;把鼠标移走div之后&#xff0c;div的背景颜色回复原来的颜色。 效果图演示 没有将鼠标放在div上时&#xff08;lanse&#xff09; 将鼠标放在div上之后&#xff08;变为红色&#xff09; 下面看代码 由于代码较短&…