基于Golang的网络爬虫GoColly

因项目需要,要对网络上某些信息进行抓取,以便加工后做数据分析。提到爬虫框架,知名度最高的当属基于Python的爬虫框架 Scrapy。但是由于本人对 Python 并不熟悉,并且暂时也不准备去深入学习,因此不在考虑范围。同时也是基于学习的目的,因此选择了 Golang 方向。基于 Golang 的成熟爬虫框架其实并不多,因此在选择上不用太纠结,就用 Go-Colly 了。

由于墙的原因,安装 Go-Colly 并不是非常顺利,至少不像官网介绍的一条命令就OK了。下面基于 CentOS-7.2/Golang-v1.11 环境,对安装做下简单的说明。

1. 安装 Golang-v1.11

Golang 的安装还是非常简单的,直接选择编译好的安装包即可。

1
2
3
4
5
6
7
8
9
# 下载
wget https://dl.google.com/go/go1.11.1.linux-amd64.tar.gz
# 放在对应目录
tar -zxf go1.11.1.linux-amd64.tar.gz -C /usr/local
# 配置环境变量
# vim /etc/profile
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
export GOPATH=/data/golang

2. 安装 Go-Colly

参考官网手册,直接执行安装命令。

1
go get -u github.com/gocolly/colly/...

执行完后看到如下报错

1
2
3
4
5
6
package github.com/gocolly/colly
	imports golang.org/x/net/html: unrecognized import path "golang.org/x/net/html" (https fetch: Get https://golang.org/x/net/html?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
package github.com/gocolly/colly
	imports golang.org/x/net/html/charset: unrecognized import path "golang.org/x/net/html/charset" (https fetch: Get https://golang.org/x/net/html/charset?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
package github.com/gocolly/colly
	imports google.golang.org/appengine/urlfetch: unrecognized import path "google.golang.org/appengine/urlfetch" (https fetch: Get https://google.golang.org/appengine/urlfetch?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)

这是由于防火墙的原因,安装过程中无法下载到某些以依赖的包。那么我们就手动来安装下。 Golang 的包在 Github 上有对应的镜像,因此我们一一手动下载下来放到对应目录即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
# net/text
mkdir -p /data/golang/src/golang.org/x
cd /data/golang/src/golang.org/x
git clone https://github.com/golang/net
git clone https://github.com/golang/text
# protobuf
mkdir -p /data/golang/src/github.com/golang
cd /data/golang/src/github.com/golang
git clone https://github.com/golang/protobuf
# appengine
mkdir /data/golang/src/google.golang.org
cd /data/golang/src/google.golang.org
git clone https://github.com/golang/appengine.git

至此,所需的包都已经配置完成。如果还有报错的,按照提示继续安装即可。

3. 试运行下demo

以下是个最基本的示例,抓取本博客的信息。

vim gocolly.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main

import (
	"fmt"
	"github.com/gocolly/colly"
)

func main() {
	// 实例化
	c := colly.NewCollector(
		// 限定域名
		colly.AllowedDomains("blog.phpha.com"),
		// 最大深度
		colly.MaxDepth(1),
	)

	// On every a element which has href attribute call callback
	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
		link := e.Attr("href")
		// Print link
		fmt.Printf("Link found: %q -> %s\n", e.Text, link)
		// Visit link found on page
		// Only those links are visited which are in AllowedDomains
		c.Visit(e.Request.AbsoluteURL(link))
	})

	// Before making a request print "Visiting ..."
	c.OnRequest(func(r *colly.Request) {
		fmt.Println("Visiting", r.URL.String())
	})

	// Start scraping on http://blog.phpha.com/
	c.Visit("http://blog.phpha.com/")
}

运行结果如下

1
2
3
4
5
6
7
# go run gocolly.go
Visiting http://blog.phpha.com/
Link found: "PHPHa" -> http://blog.phpha.com/
Link found: "首页" -> http://blog.phpha.com/
Link found: "归档" -> http://blog.phpha.com/archives
Visiting http://blog.phpha.com/archives
...