【Go 入门学习】第一篇关于 Go 的博客--Go 爬虫初体验
一、写在前面
其实早就该写这一篇博客了,为什么一直没有写呢?还不是因为忙不过来(实际上只是因为太懒了)。不过好了,现在终于要开始写这一篇博客了。在看这篇博客之前,可能需要你对 Go 这门语言有些基本的了解,比如基础语法之类的。话不多说,进入正题。
二、Go 环境配置
1.安装配置
在学习一门语言时,第一步就是环境配置了,Go 也不例外,下面就是 Windows 下 Go 开发环境的配置过程了。
首先你需要下载 Go 的安装包,可以打开 Go 语言中文网下载,地址为:https://studygolang.com/dl。
下载完成后打开安装(例如安装到 E:\Go 目录),然后配置环境变量,将安装目录下的 bin 目录路径加入环境变量中。这一步完成后打开命令行,输入 go version,若出现版本信息则表明配置成功。
2.配置 GOPATH 和 GOROOT
除了要将 bin 目录加入到环境变量中,还要配置 GOPATH 和 GOROOT,步骤如下:
在用户变量中新建变量 GOPATH:

在系统变量中新建变量 GOROOT:

3. 选择 IDE
在 IDE 的选择上,我比较推荐使用 jetbrains 家的 GoLand,功能强大,使用起来也很方便。
三、下载网页
下载网页使用的是 Go 中原生的 http 库,在使用前需要导包,和 Python 一样用 import 导入即可。如果要发送 GET 请求,可以直接使用 http 中的 Get() 方法,例如:
package main import (
"fmt"
"net/http"
) func main () {
html, err := http.Get("https://www.baidu.com/")
if err != nil {
fmt.Println(err)
}
fmt.Println(html)
}
Get() 方法有两个返回值,html 表示请求的结果,err 表示错误,这里必须对 err 做判断,Go 语言的错误机制就是这样,这里不多做解释。
这么用起来确实很简单,但是不能自己设置请求头,如果要构造请求头的话可以参考下面的例子:
req, _ := http.NewRequest("GET", url, nil)
// Set User-Agent
req.Header.Add("UserAgent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36")
client := &http.Client{}
resp, err := client.Do(req)
四、解析网页
1.解析库选择
Go 语言中可以用来解析网页的库也是很齐全的,XPath、CSS 选择器和正则表达式都能用。这里我用的是 htmlquery,这个库使用的是 Xpath 选择器。htmlquery 是用于 HTML 的 XPath 数据提取库,可通过 XPath 表达式从 HTML 文档中提取数据。Xpath 语法就不提了,毕竟用 Python 写爬虫的时候没少用。
先说下 htmlquery 的安装吧,一般会推荐你使用如下命令安装:
go get github.com/antchfx/htmlquery
但是你懂的,出于某些原因就下载不下来,怎么办呢?对于这种能在 GitHub 上找到的库直接 clone 到本地就行了,记得要复制到你的 GOAPTH 下。
2.使用 htmlquery
在使用 htmlquery 这个库的时候,可能会报错说缺少 golang.org\x\text,和上面的解决办法一样,去 GitHub 上找,然后 clone 下来。
下面是 htmlquery 中经常使用的方法及相应含义:
func Parse(r io.Reader) (*html.Node, error): 返回给定 Reader 的 HTML 的解析树。
func Find(top *html.Node, expr string) []*html.Node: 搜索与指定 XPath 表达式匹配的 html.Node。
func FindOne(top *html.Node, expr string) *html.Node: 搜索与指定 XPath 表达式匹配的 html.Node,并返回匹配的第一个元素,可简单理解为FindOne = Find[0]。
func InnerText(n *html.Node) string: 返回对象的开始和结束标记之间的文本。
func SelectAttr(n *html.Node, name string) (val string): 返回指定名称的属性值。
func OutputHTML(n *html.Node, self bool) string: 返回包含标签名称的文本。
下面是使用 htmlquery 解析网页的代码:
// Used to parse html
func parse(html string) {
// Parse html
root, _ := htmlquery.Parse(strings.NewReader(html))
titleList := htmlquery.Find(root, `//*[@id="post_list"]/div/div[2]/h3/a/text()`)
hrefList := htmlquery.Find(root, `//*[@id="post_list"]/div/div[2]/h3/a/@href`)
authorList := htmlquery.Find(root, `//*[@id="post_list"]/div/div[2]/div/a/text()`) // Traverse the result
for i := range titleList {
blog := BlogInfo{}
blog.title = htmlquery.InnerText(titleList[i])
blog.href = htmlquery.InnerText(hrefList[i])
blog.author = htmlquery.InnerText(authorList[i])
fmt.Println(blog)
}
}
需要注意的是由于在 Go 语言中不支持使用单引号来表示字符串,而要使用反引号“`”和双引号来表示字符串。然后因为 Find() 方法返回的是一个数组,因而需要遍历其中每一个元素,使用 for 循环遍历即可。在 for 循环中使用到的 BlogInfo 是一个结构体,表示一个博客的基本信息,定义如下:
// Used to record blog information
type BlogInfo struct {
title string
href string
author string
}
五、Go 并发
在 Go 语言中使用 go 关键字开启一个新的 go 程,也叫 goroutine,开启成功之后,go 关键字后的函数就将在开启的 goroutine 中运行,并不会阻塞当前进程的执行,所以要用 Go 来写并发还是很容易的。例如:
baseUrl := "https://www.cnblogs.com/"
for i := 2; i < 4; i ++ {
url := baseUrl + "#p" + strconv.Itoa(i)
// fmt.Println(url)
go request(url)
} // Wait for goroutine
time.Sleep(2 * time.Second)
request(baseUrl)
这里除了在主进程中有一个 request(),还开启了两个 go 程来执行 request()。不过要注意的是,一旦主进程结束,其余 Go 程也会结束,所以我这里加了一个两秒钟的等待时间,用于让 Go 程先结束。
六、体验总结
由于我本身才刚开始学习 Go,就还有很多东西没有学到,所以这个初体验其实还有很多没写到的地方,比如数据保存,去重问题等等,后面会去多看看 Go 的官方文档。当然了,对我来说,要写爬虫的话还是会用 Python 来写的,不过还是得花时间学习新知识,比如使用 Go 做开发,熟悉掌握 Go 语言就是我的下一目标了。
完整代码已上传到 GitHub!
【Go 入门学习】第一篇关于 Go 的博客--Go 爬虫初体验的更多相关文章
- VHDL语法入门学习第一篇
1. 现在先遇到一个VHDL的语法问题,以前没用过VHDL,现在要去研究下,进程(PROCESS) 进程内部经常使用IF,WAIT,CASE或LOOP语句.PROCESS具有敏感信号列表(sensit ...
- LAUNCHXL-28379D入门学习-第一篇
1. 首先安装controlSUITE或者C2000ware软件,TI官网下载,安装后包括C2000的函数库和例程之类的,还可以和CCS搭配使用.controlSUITE安装完之后大约4个G,所以我安 ...
- Python入门学习笔记4:他人的博客及他人的学习思路
看其他人的学习笔记,可以保证自己不走弯路.并且一举两得,即学知识又学方法! 廖雪峰:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958 ...
- Entity Framework 6.0 入门系列 第一篇
Entity Framework 6.0 入门系列 第一篇 好几年前接触过一些ef感觉不是很好用,废弃.但是 Entity Framework 6.0是经过几个版本优化过的产物,性能和功能不断完善,开 ...
- LINQ to XML LINQ学习第一篇
LINQ to XML LINQ学习第一篇 1.LINQ to XML类 以下的代码演示了如何使用LINQ to XML来快速创建一个xml: public static void CreateDoc ...
- 从.Net到Java学习第一篇——开篇
以前我常说,公司用什么技术我就学什么.可是对于java,我曾经一度以为“学java是不可能的,这辈子不可能学java的.”结果,一遇到公司转java,我就不得不跑路了,于是乎,回头一看N家公司交过社保 ...
- Elasticsearch7.X 入门学习第一课笔记----基本概念
原文:Elasticsearch7.X 入门学习第一课笔记----基本概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https: ...
- Java并发包下锁学习第一篇:介绍及学习安排
Java并发包下锁学习第一篇:介绍及学习安排 在Java并发编程中,实现锁的方式有两种,分别是:可以使用同步锁(synchronized关键字的锁),还有lock接口下的锁.从今天起,凯哥将带领大家一 ...
- JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇
JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇 作为一个使用Java语言开发的程序员,我们都知道,要想运行Java程序至少需要安装JRE(安装JDK也没问题).我们也知道我们Java程序 ...
随机推荐
- 本人亲测-SSM环境搭建(使用eclipse作为示例,过程挺全的,可作为参考)
本人亲测-SSM环境搭建(使用eclipse作为示例,过程挺全的,可作为参考) 本人亲测-SSM环境搭建(使用eclipse作为示例,过程挺全的,可作为参考) 本人亲测-SSM环境搭建(使用eclip ...
- python-犯傻合集
1.题目: 基于文件实现用户登录程序,提示用户输入用户名和密码,检查用户名是否存在,以及用户名密码是否正确 保存密码的文件叫user.txt,内容: | 作分隔符 阶段一: 自己第一次的答案: ...
- 微信小程序与用户交互
微信小程序与用户交互 一.显示消息提示框 wx.showToast({属性名:属性值}) 自定义一个提示框,时间到了会自动关闭 wx.showToast({ title:"成功", ...
- Tree 点分治
题目描述 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K 输入输出格式 输入格式: N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是 ...
- ajax 轮询(适合web端二维码请求)
(前几天 一直弄二维码轮询登录 想了半天 总算弄出来了 分享给大家 ^-^) 轮询: 所谓轮询 肯定需要 setInterval 但是怎么加ajax请求 需要有点小问题而且轮询成功后需要停 ...
- Windows突破远程连接最大数去掉限制登录
当对方设置最大连接数 超过限制时 可以用这个命令 win+r 输入 mstsc /v:192.168.18.131:3389 /console windows server 2003 sp2 以 ...
- vue入门笔记(新手入门必看)
一.什么是Vue? 1. vue为我们提供了构建用户界面的渐进式框架,让我们不再去操作dom元素,直接对数据进行操作,让程序员不再浪费时间和精力在操作dom元素上,解放了双手,程序员只需要关心业 ...
- java 连续数字数组分组
问题: 1. 将Lis list = Arrays.asList(1,2,3,5,8,9,10), 拆分成 [1,2,3] .[5]. [8,9,10] , 2. 再传入一个数字 9, 将匹配数字9的 ...
- Mutex vs Semaphore vs Monitor vs SemaphoreSlim
C#开发者(面试者)都会遇到Mutex,Semaphore,Monitor,SemaphoreSlim这四个与锁相关的C#类型,本文期望以最简洁明了的方式阐述四种对象的区别. 线程安全 教条式理解 如 ...
- 玩转OneNET物联网平台之MQTT服务⑦ —— 远程控制LED(数量无限制)+ Android App控制 优化第一版
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...