使用Go語言實現爬蟲功能

晦若晨曦發表於2017-12-14

先上程式碼:

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語言道路上的第一步。

相關文章