先上代码:
Github
Go语言其实很早就有了,但是最近才火起来。有Google爸爸做靠山,这个语言的前景是非常被看好的。
不同于流行的java,php,javascript,python等语言,Go语言是更接近于C/C++的底层语言。不需要虚拟机或者容器之类的运行环境。这就为它的执行效率和可控性提供了很大的保障。
Go语言的语法很简单,而且提供了常用的标准库,更优雅的API。这是它相对于C/C++语言很大的进步之一。极大的降低了使用者的学习成本。
Go的优势在于天生的异步能力。能够通过极为简洁优雅的方式实现多线程的编程。而Go对于变量的种种限制,简直就是某些强迫症患者的福音。
学习Go语言之后,用它写了一个简单的爬虫以做练习。
首先呢,要爬的网站是4chan,恩恩,可以帮你打开新世界的大门的那种。
上来先定义一个结构体:
//ThreadItem 帖子数据
type ThreadItem struct {
url string //帖子路径
content string //帖子内容
imgs []string //帖子图片
}
要爬取网页,首先要通过http下载网页内容:
func httpGet(url string) (content string, statusCode int) {
resp, err1 := http.Get(url)
if err1 != nil {
statusCode = -100
return
}
defer resp.Body.Close()
data, err2 := ioutil.ReadAll(resp.Body)
if err2 != nil {
statusCode = -200
return
}
statusCode = resp.StatusCode
content = string(data)
return
}
http是GO语言提供的标准库之一,可以发起和接受http请求。ioutil也是标准库之一,功能顾名思义。 使用defer关键字,来保证在执行后关闭http连接。
通过httpGet方法可以请求到页面数据。这个方法在有两处使用,第一处是在开始调用此方法,获取到一个index页面。然后在index页面中解析出帖子路径后,通过此方法填充ThreadItem中的content字段。
第二件事则是通过正则表达式解析出页面中有价值的数据,在此爬虫中利用了两个正则:
var (
//图片正则表达式
imageItemExp = regexp.MustCompile(`src="//i\.4cdn\.org/s/[0123456789]+s\.jpg"`)
//帖子路径正则表达式
threadItemExp = regexp.MustCompile(`"thread/[0123456789]+"`)
)
此处以解析帖子路径为例,展示正则的使用方式:
//解析正则表达式,返回参数tds是一个数组
tds := threadItemExp.FindAllStringSubmatch(content, 10000)
var tdStr = make([]string, 0)
//去掉引号,并放到一维数组中
for _, t := range tds {
var n = strings.Replace(t[0], "\"", "", -1)
tdStr = append(tdStr, n)
}
var threads = make([]ThreadItem, 0)
//组装帖子结构体
for _, t := range tdStr {
threads = append(threads, ThreadItem{url: "http://boards.4chan.org/s/" + t})
}
return threads
通过此方法就成功的获取到了一堆的帖子结构体。
go语言傲娇的取消了“类”这种东西,但是还是允许给结构体指定方法。在实际的调用上,和平常的类感受是差不多的。
最后一件事情就是下载图片了。对于go来说,下载图片和下载网页内容的操作是基本一致的,都是通过http.Get方法来获取数据。所以不再累述。在此值得一说的是对文件系统的操作。
最核心的代码就这三行:
//创建目录
err := os.Mkdir(dir, os.ModePerm)
//创建文件
file, err := os.Create(dir + "/" + filename)
//写入数据
file.Write(data)
看源码可知Go中对于error的处理还是挺繁琐的,简简单单的三行代码需要进行好多次的错误判断。不过从另一个角度上来说也算强制的进行防御性编程,提高了代码可可靠性。
至此一个GO语言的爬虫就初步完成了。虽然很简单,但是也算是学习Go语言道路上的第一步。