阅读 4221
花三个小时入门了GO,还写了个爬虫?| 🏆 技术专题第二期征文

花三个小时入门了GO,还写了个爬虫?| 🏆 技术专题第二期征文

纸上得来终觉浅,绝知此事要躬行。

这两天看到了掘金的GO征文活动,看着奖品有小册兑换码,我不禁心动了起来,不过转念一想,自己根本没接触过GO,怎么写得好征文呢?

想到这,我摇了摇头,男人怎么能说不行,既然我从不了解GO,我现学不就行了,把学完的感受与总结写下来,不是更贴合此次征文的主题?

可以参考的技术主题 : golang入门系列

说干就干,我直接打开百度搜索go浏览了第一页之后,找到两个入门级的教程和官网,就开始了我的Golang入门之旅。

1. 安装

Golang官网小白学习第一步,装环境。

我首先打开官网用我初中的英语水平准确找到了windows环境安装包的下载链接,像现在的所有语言一样,双击 -> 安装 -> Next Step -> Finish一气呵成,安装就像喝水一样简单。

因为有着Java的安装经验,所以我熟练的打开DOS窗口,分别输入:go versiongo env命令进行测试。

go安装

看到这两个命令都输出了预想中的结果,我欣慰的笑了笑,安装,不过如此。

不过我注意到网上的教程都让我安装之后先设置一个叫GO-PATH的东西,是熟悉的感觉,我仿佛又回到了四年前初学Java的下午,安装完JDK的第一步也是要设置一下JAVA-PATH,现在的JDK已经不需要手动设置了,安装的时候就已经设置好了。

GO语言作为一门新兴语言总不能还有这种历史包袱吧,我怀着悲痛的心情点开了电脑的环境变量:

go环境变量

果然,系统已经帮我设置好了,不用我去手动设置了。

不过坑爹的是这个目录下我原先并没有go文件夹,它居然也没有帮我创建,而且根据GO的规定,你每个项目都要在这里指定一次的环境变量,也就是说如果电脑上有10个项目,你就要在GO-PATH后面写10个项目的文件夹地址,一点也不自由了~~~~

好了不说这个,环境变量既然好了,那我们就可以编写我们的Hello-World了,Hello-World入门必敲。

2. Hello-World

Golang官网上面有一段代码,教你如何用GO输出Hello-World,我COPY下来就准备贴了。

但是转念一想,根据GO的规定要在go项目的文件夹下必须有binpkgsrc目录,我直接用默认的go文件夹作为项目的根目录,所以我就在这下面又手动建了这三个文件夹。

建好了之后,我打开万能编辑器-VSCODE,下载一个go语言支持,就开写了。

准备写的时候呢,这个VSCODE又提醒我要安装一堆插件:

go插件

从这堆东西的名字看来,应该是go相关的工具包,不过因为是连GitHub下载我几次下载都失败了,最好在网上找了方法,可以用go-proxy来设置国内代理,不过我设置好了之后依旧是从GitHub下载,最后重启了一下VSCODE才慢吞吞的下载好(依旧是从GITHUB下载)。

这些准备工作做好之后,我在src包下编写了我的第一个GO程序-Hello-World,新建一个以go.go文件,然后把官网的代码copy进去如下:

package main

import "fmt"

func main() {
	fmt.Println("Hello, 世界")
}
复制代码

这样我们的程序就编写好了,紧接着进行手动编译运行,go提供了go buildgo run命令帮助我们编译运行。

go-hello-world

go build命令是编译,go run是编译后运行,不过他俩还有其他区别,暂时可以只记这么多。


我可以再简要说说这段Hello-World代码,package main声明这是主函数的入口类,import "fmt"则是我们用到了go内置的fmt包,最后是定义了一个名为main的函数,使用fmt包下的Println进行字符串打印。

如果你有其他语言的基础,这点东西太小kiss了。

3. 巧遇拦路虎

接下来我准备仗着自己有点Java基础,直接写一个爬虫来练练手,我看大家都是爬豆瓣电影TOP250练手,我就爬豆瓣读书TOP250吧。

在这之前,我没有看过任何关于GO的东西,仅仅看了如何定义变量,的确有点反常识,因为Go语言的变量定义是把类型放在后面,我给大家演示一下:

var str string
复制代码

第一次看到的时候的确一点也不喜欢,因为太有违我的习惯了,不过真正写起来之后发现还真不是这么回事,Go有点像JS,它的类型是可以直接推断的,加之GO定义变量有个简单写法:

str := "和耳朵真棒!"
复制代码

我们平常可以用这种简单写法来写,这代表变量赋值二合一。

在后面我写爬虫的时候基本都是用这种方式来定义变量的,根本轮不到自己去指定类型。

语法什么的都不是问题,我遇到的第一个问题是导包,因为要写爬虫,我起码要有一个DOM树解析的工具,不然自己正则写起来要累死了。

在最开始的时候我还在嘲笑GO居然非要把项目放在GOPATH下面,后来在导包这个问题上面我查了查资料发现自从GO引入了mod模块之后已经可以把项目放在任何一个文件夹了。

mod模块用我的理解就是一个包管理器,把平常项目中需要用到的包都下载起来,然后项目用到的时候直接导,没有的话就去远程下载,类似Java中的Maven和Gradle概念。

既然牵扯到包了,那远程的肯定慢啊,必须要加入国内镜像才能快起来:

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
复制代码

加入国内镜像之后,就可以愉快的下载我们所需要的包了:

go get github.com/PuerkitoBio/goquery
复制代码

goquery类似jquery,它是jquery的go版本实现,使用它,可以很方便的对HTML进行处理。

说白了就是一个方便操作DOM树的一个工具而已。

下载好依赖之后,我们就可以创建自己的项目了~

随便找一个文件夹,打开dos输入go mod init xxx,即可初始化自己的GO项目,这个XX指的是本项目的名字,然后这个文件夹下面就会出现go.mod文件,这个文件记录了项目中引入了那些依赖,慢慢还会出现go.sum文件,都是自动生成,不用理会,专注编码即可。

4. 爬取豆瓣读书TOP250

我在创建了一个hello-go文件夹,初始化之后,建立了一个go.go文件,编写好main函数之后,我们的程序主体就可以开始编写了。

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

func main() {

	// 创建我们要导出的TXT文件
	file, err := os.Create("豆瓣读书TOP250.txt")
	if err != nil {
		fmt.Println(err)
	}
	defer file.Close()

	// 创建一个客户端对象,用于发送请求
	var client = http.Client{}

	for i := 0; i < 250; i += 25 {
		// 发送一条新请求
		req, _ := http.NewRequest("GET", "https://book.douban.com/top250?start="+strconv.Itoa(i), nil)
		// 设置User-Agent 必须
		req.Header.Set("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)")

		// 发送请求
		resp, err := client.Do(req)
		// 处理异常
		if err != nil {
			fmt.Println("http get error", err)
			return
		}
		// 关闭流
		defer resp.Body.Close()

		// 通过goquery将流中的内容构建成一棵DOM树
		doc, err := goquery.NewDocumentFromReader(resp.Body)
		if err != nil {
			log.Fatal(err)
		}

		// 拿到所有标记的节点集合
		// 并进行each循环,i = 序号,s = 节点本身
		doc.Find("div.indent>table>tbody>tr.item").Each(func(i int, s *goquery.Selection) {
			// 拿到节点集合中的Items
			item := s.Find("td[valign=top]")

			// 通过Item节点获取到我们所需要的数据
			// 对数据进行去空格 去换行操作
			bookName := strings.Replace(strings.Replace(item.Find("div.pl2>a").Text(), "\n", "", -1), " ", "", -1)

			author := strings.Split(s.Find("p.pl").Text(), "/")[0]

			quote := strings.Replace(strings.Replace(s.Find("p.quote").Text(), "\n", "", -1), " ", "", -1)

			// 拿到我们已经处理好的数据之后 接下来就是往TXT里面填充了

			//fmt.Print("TOP" + fmt.Sprint(i) + "-" + bookName + "-" + author + "-" + quote)

			// 处理字符直接的空格长度,尽力对齐
			bookName = bookName + strings.Repeat(" ", (120-len(bookName)))
			author = author + strings.Repeat(" ", (50-len(author)))

			content := "TOP" + strconv.Itoa(i) + "\t" + bookName + author + quote + "\n"

			file.WriteString(content)
		})
	}

	fmt.Print("程序执行完毕,请查看结果。")

}
复制代码

小伙伴们可以直接粘贴到自己编辑器中,包什么的会自动导入的,然后运行此文件即可。

这里面的代码基本都是我到处搜索:

  • go 如何发送请求?
  • go 如何去除字符串空格?
  • go 如何拿到字符串长度?
  • go 如何读写文件?

我都是遇山开山,遇水搭桥一步步的找齐我自己需要用到的知识点,然后把他们凑到一块~~~~

给大家看看效果:

GO爬虫效果展示

导出Excel的话就更完美了,对了,run大家应该会把: go run go.go即可。

好了,今天的征文就到这里,总体看下来GO还是用起来挺方便的,就是时间太短,没有好好学习GO的并发的相关知识~~~

下期见。

🏆 技术专题第二期 | 我与 Go 的那些事......

文章分类
后端
文章标签