使用Go語言(golang)寫個簡單的爬蟲


上次用Scala寫了個爬蟲。最近在閑工夫之時,學習Go語言,便用Go移植了那個用Scala寫的爬蟲,代碼如下:

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
)

var (
	ptnIndexItem    = regexp.MustCompile(`<a target="_blank" href="(.+\.html)" title=".+" >(.+)</a>`)
	ptnContentRough = regexp.MustCompile(`(?s).*<div class="artcontent">(.*)<div id="zhanwei">.*`)
	ptnBrTag        = regexp.MustCompile(`<br>`)
	ptnHTMLTag      = regexp.MustCompile(`(?s)</?.*?>`)
	ptnSpace        = regexp.MustCompile(`(^\s+)|( )`)
)

func Get(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
}

type IndexItem struct {
	url   string
	title string
}

func findIndex(content string) (index []IndexItem, err error) {
	matches := ptnIndexItem.FindAllStringSubmatch(content, 10000)
	index = make([]IndexItem, len(matches))
	for i, item := range matches {
		index[i] = IndexItem{"http://www.yifan100.com" + item[1], item[2]}
	}
	return
}

func readContent(url string) (content string) {
	raw, statusCode := Get(url)
	if statusCode != 200 {
		fmt.Print("Fail to get the raw data from", url, "\n")
		return
	}

	match := ptnContentRough.FindStringSubmatch(raw)
	if match != nil {
		content = match[1]
	} else {
		return
	}

	content = ptnBrTag.ReplaceAllString(content, "\r\n")
	content = ptnHTMLTag.ReplaceAllString(content, "")
	content = ptnSpace.ReplaceAllString(content, "")
	return
}

func main() {
	fmt.Println(`Get index ...`)
	s, statusCode := Get("http://www.yifan100.com/dir/15136/")
	if statusCode != 200 {
		return
	}
	index, _ := findIndex(s)

	fmt.Println(`Get contents and write to file ...`)
	for _, item := range index {
		fmt.Printf("Get content %s from %s and write to file.\n", item.title, item.url)
		fileName := fmt.Sprintf("%s.txt", item.title)
		content := readContent(item.url)
		ioutil.WriteFile(fileName, []byte(content), 0644)
		fmt.Printf("Finish writing to %s.\n", fileName)
	}
}

  代碼行數比Scala版的有一定增加,主要原因有以下幾方面原因:
1 golang 重視代碼書寫規范,或者說代碼格式,很多地方寫法比較固定,甚至比較麻煩。比如就算是if判斷為真后的執行語句只有一句話,按照代碼規范,也要寫出帶大括號的三行,而在Scala和很多其他語言中,一行就行;
2 golang 的strings包和regexp包提供的方法並不特別好用,特別是和Scala相比,使用起來感覺Scala的正則和字符串處理要舒服的多;
3 scala版的爬蟲里面用到了Scala標准庫中的實用類和方法,它們雖然不是語法組成,但用起來感覺像是語法糖,這里很多方法和函數式編程有關,golang的函數式編程還沒有去仔細學習。

  當然golang版的爬蟲也有一個優勢,就是編譯速度很快,執行速度在現在的寫法里面體現不出優勢;golang的特性goroutine在這里沒有用到,這段代碼今后會不斷改進。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM