用Golang寫爬蟲(一)

以前一直都是再用Python寫爬蟲,最近想體驗下Golang寫爬蟲的感受,因此就有了這個系列。我想要抓取的頁面是豆瓣Top250頁面,選擇它的理由有3個:html

  1. 豆瓣頁面代碼相對規範
  2. 豆瓣對爬蟲愛好者相對更寬容
  3. Top250頁面簡潔,很適合拿來練手

咱們先看初版的代碼。git

按邏輯我把抓取代碼分紅2個部分:github

  1. HTTP請求
  2. 解析頁面中的內容

咱們先看HTTP請求,Golang語言的HTTP請求庫不須要使用第三方的庫,標準庫就內置了足夠好的支持:golang

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

func fetch (url string) string {
	fmt.Println("Fetch Url", url)
	client := &http.Client{}
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Http get err:", err)
        return ""
	}
	if resp.StatusCode != 200 {
		fmt.Println("Http status code:", resp.StatusCode)
		return ""
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Read error", err)
		return ""
	}
	return string(body)
}
複製代碼

我把URL請求的邏輯都放在了fetch函數中,裏面作了一些異常處理。值得說的有2點:web

  1. 在Header中設置了User-Agent,讓訪問看起來更像搜索引擎Bot。若是一個網站但願本身的內容被Google收錄那麼他就不會拒絕這樣的UA的訪問。
  2. 須要經過ioutil.ReadAll 讀取resp的body內容,最後用string(body)把它轉化成字符串

接着就是解析頁面的部分:正則表達式

import (
    "regexp"
	"strings"
)

func parseUrls(url string) {
	body := fetch(url)
	body = strings.Replace(body, "\n", "", -1)
	rp := regexp.MustCompile(`<div class="hd">(.*?)</div>`)
	titleRe := regexp.MustCompile(`<span class="title">(.*?)</span>`)
	idRe := regexp.MustCompile(`<a href="https://movie.douban.com/subject/(\d+)/"`)
	items := rp.FindAllStringSubmatch(body, -1)
	for _, item := range items {
		fmt.Println(idRe.FindStringSubmatch(item[1])[1],
			titleRe.FindStringSubmatch(item[1])[1])
	}
}
複製代碼

這篇文章咱們主要體驗用標準庫完成頁面的解析,也就是用正則表達式包regexp來完成。不過要注意須要用strings.Replace(body, "\n", "", -1)這步把body內容中的回車符去掉,要否則下面的正則表達式.*就不符合了。FindAllStringSubmatch方法會把符合正則表達式的結果都解析出來(一個列表),而FindStringSubmatch是找第一個符合的結果。bash

Top250頁面是要翻頁的,最後在main函數裏面實現抓取所有Top250頁面。另外爲了和以後的改進作對比,咱們加上代碼運行耗時的邏輯:函數

import (
       "time"
       "strconv"
)
func main() {
        start := time.Now()
        for i := 0; i < 10; i++ {
                parseUrls("https://movie.douban.com/top250?start=" + strconv.Itoa(25 * i))
        }
        elapsed := time.Since(start)
        fmt.Printf("Took %s", elapsed)
}
複製代碼

在Golang中把數字轉成字符串須要使用strconv.Itoa(嘿嘿,本博客域名就是這個模塊),這樣就能夠根據start的參數的不通拼出正確的頁面路徑。用一個for循環完成翻頁。post

運行起來很是快:fetch

❯ go run crawler/doubanCrawler1.go
... # 省略輸出
Took 1.454627547s
複製代碼

經過終端輸出能夠看到咱們拿到了對應電影條目的ID和電影標題!

代碼地址

完整代碼能夠在這個地址找到。

原文地址:strconv.com/posts/web-c…

相關文章
相關標籤/搜索