一、写在前面

  其实早就该写这一篇博客了,为什么一直没有写呢?还不是因为忙不过来(实际上只是因为太懒了)。不过好了,现在终于要开始写这一篇博客了。在看这篇博客之前,可能需要你对 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 爬虫初体验的更多相关文章

  1. VHDL语法入门学习第一篇

    1. 现在先遇到一个VHDL的语法问题,以前没用过VHDL,现在要去研究下,进程(PROCESS) 进程内部经常使用IF,WAIT,CASE或LOOP语句.PROCESS具有敏感信号列表(sensit ...

  2. LAUNCHXL-28379D入门学习-第一篇

    1. 首先安装controlSUITE或者C2000ware软件,TI官网下载,安装后包括C2000的函数库和例程之类的,还可以和CCS搭配使用.controlSUITE安装完之后大约4个G,所以我安 ...

  3. Python入门学习笔记4:他人的博客及他人的学习思路

    看其他人的学习笔记,可以保证自己不走弯路.并且一举两得,即学知识又学方法! 廖雪峰:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958 ...

  4. Entity Framework 6.0 入门系列 第一篇

    Entity Framework 6.0 入门系列 第一篇 好几年前接触过一些ef感觉不是很好用,废弃.但是 Entity Framework 6.0是经过几个版本优化过的产物,性能和功能不断完善,开 ...

  5. LINQ to XML LINQ学习第一篇

    LINQ to XML LINQ学习第一篇 1.LINQ to XML类 以下的代码演示了如何使用LINQ to XML来快速创建一个xml: public static void CreateDoc ...

  6. 从.Net到Java学习第一篇——开篇

    以前我常说,公司用什么技术我就学什么.可是对于java,我曾经一度以为“学java是不可能的,这辈子不可能学java的.”结果,一遇到公司转java,我就不得不跑路了,于是乎,回头一看N家公司交过社保 ...

  7. Elasticsearch7.X 入门学习第一课笔记----基本概念

    原文:Elasticsearch7.X 入门学习第一课笔记----基本概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https: ...

  8. Java并发包下锁学习第一篇:介绍及学习安排

    Java并发包下锁学习第一篇:介绍及学习安排 在Java并发编程中,实现锁的方式有两种,分别是:可以使用同步锁(synchronized关键字的锁),还有lock接口下的锁.从今天起,凯哥将带领大家一 ...

  9. JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇

    JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇 作为一个使用Java语言开发的程序员,我们都知道,要想运行Java程序至少需要安装JRE(安装JDK也没问题).我们也知道我们Java程序 ...

随机推荐

  1. 本人亲测-SSM环境搭建(使用eclipse作为示例,过程挺全的,可作为参考)

    本人亲测-SSM环境搭建(使用eclipse作为示例,过程挺全的,可作为参考) 本人亲测-SSM环境搭建(使用eclipse作为示例,过程挺全的,可作为参考) 本人亲测-SSM环境搭建(使用eclip ...

  2. python-犯傻合集

    1.题目: 基于文件实现用户登录程序,提示用户输入用户名和密码,检查用户名是否存在,以及用户名密码是否正确 保存密码的文件叫user.txt,内容:   |  作分隔符 阶段一: 自己第一次的答案: ...

  3. 微信小程序与用户交互

    微信小程序与用户交互 一.显示消息提示框 wx.showToast({属性名:属性值}) 自定义一个提示框,时间到了会自动关闭 wx.showToast({ title:"成功", ...

  4. Tree 点分治

    题目描述 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K 输入输出格式 输入格式: N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是 ...

  5. ajax 轮询(适合web端二维码请求)

    (前几天 一直弄二维码轮询登录 想了半天 总算弄出来了 分享给大家    ^-^) 轮询: 所谓轮询 肯定需要 setInterval   但是怎么加ajax请求  需要有点小问题而且轮询成功后需要停 ...

  6. Windows突破远程连接最大数去掉限制登录

    当对方设置最大连接数 超过限制时 可以用这个命令 win+r  输入 mstsc /v:192.168.18.131:3389 /console   windows server 2003 sp2 以 ...

  7. vue入门笔记(新手入门必看)

    一.什么是Vue? 1.    vue为我们提供了构建用户界面的渐进式框架,让我们不再去操作dom元素,直接对数据进行操作,让程序员不再浪费时间和精力在操作dom元素上,解放了双手,程序员只需要关心业 ...

  8. java 连续数字数组分组

    问题: 1. 将Lis list = Arrays.asList(1,2,3,5,8,9,10), 拆分成 [1,2,3] .[5]. [8,9,10] , 2. 再传入一个数字 9, 将匹配数字9的 ...

  9. Mutex vs Semaphore vs Monitor vs SemaphoreSlim

    C#开发者(面试者)都会遇到Mutex,Semaphore,Monitor,SemaphoreSlim这四个与锁相关的C#类型,本文期望以最简洁明了的方式阐述四种对象的区别. 线程安全 教条式理解 如 ...

  10. 玩转OneNET物联网平台之MQTT服务⑦ —— 远程控制LED(数量无限制)+ Android App控制 优化第一版

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...