隨著網路的普及,大量的資訊需要我們去獲取,而其中很大一部分的資訊是需要我們從網站上進行爬取。爬取方式有很多,其中使用golang編寫的爬蟲能夠幫助我們更有效率地獲取這些資訊。
golang是一種直覺、簡潔、高效的程式語言,適合高並發、高效能的應用場景,而爬蟲就是一種高並發、高性能的任務,因此用golang編寫爬蟲是十分合適的。在本文中,我們將介紹golang編寫爬蟲的基本流程、常用函式庫和核心技術,幫助初學者快速掌握golang爬蟲的基本方法。
一、golang 寫爬蟲的基本步驟
在介紹golang寫爬蟲的基本步驟之前,我們需要先了解一下基本的HTML結構。
在golang的標準庫中,已經提供了HTTP請求的相關函數,我們只需透過設定URL、請求頭、cookies、請求參數等基本訊息,即可建構自己所需的HTTP請求。主要程式碼如下:
package main import ( "fmt" "io/ioutil" "net/http" ) func main() { resp, err := http.Get("http://www.baidu.com") if err != nil { fmt.Println(err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
這段程式碼使用http.Get函數發起一個HTTP請求,並從回應中讀取回應體。關鍵點在於defer語句,語句會在函數結束時執行,用於關閉響應體,避免資源外洩。
HTTP請求所得到的回應資料是HTML文檔,我們需要對其進行解析,以便取得所需的資料。在golang中,我們可以使用GoQuery函式庫對HTML文件進行解析。該函式庫基於jQuery的語法,易於上手。
GoQuery提供的主要解析函數有:Find、Filter、Each和Attr等。其中Find函數用於尋找符合條件的子元素,而Filter函數用於過濾符合條件的元素。 Each函數用於遍歷所有符合條件的元素,而Attr函數則用於取得元素的屬性。以解析百度首頁為例,程式碼如下:
package main import ( "fmt" "github.com/PuerkitoBio/goquery" "log" ) func main() { resp, err := http.Get("http://www.baidu.com") if err != nil { log.Fatal(err) } body := resp.Body defer body.Close() doc, err := goquery.NewDocumentFromReader(body) if err != nil { log.Fatal(err) } doc.Find("title").Each(func(i int, s *goquery.Selection) { fmt.Println(s.Text()) }) }
以上程式碼中使用goquery.NewDocumentFromReader函數建構文檔對象,然後透過Find方法查找title元素,並透過Each方法遍歷所有符合條件的元素,輸出其文字.
最後一步是將取得到的資料儲存下來。對於資料的存儲,我們有多種方式可供選擇,如資料庫、檔案、快取等。
例如我們要將爬取到的資料儲存到CSV檔案中,步驟如下:
package main import ( "encoding/csv" "log" "os" ) func main() { file, err := os.Create("data.csv") if err != nil { log.Fatal(err) } defer file.Close() writer := csv.NewWriter(file) defer writer.Flush() writer.Write([]string{"name", "address", "tel"}) writer.Write([]string{"John Smith", "123 Main St, Los Angeles, CA 90012", "123-456-7890"}) writer.Write([]string{"Jane Smith", "456 Oak Ave, San Francisco, CA 94107", "123-456-7891"}) }
以上程式碼中使用os.Create函數建立了一個名為data.csv的文件,然後透過csv.NewWriter函數建立一個CSV寫入器。最後我們將要保存的資料透過writer.Write方法寫入到CSV檔案中。
二、golang 寫爬蟲常用函式庫
golang寫爬蟲不需要自己寫大量的底層程式碼,常見的爬蟲函式庫如下:
Gocolly是一款基於golang的輕量級爬蟲框架,提供了許多方便的方法來幫助爬取資料。它能夠自動處理重定向、cookie、代理、限速等問題,可以讓我們更專注於定義資料擷取規則。以下程式碼示範如何使用Gocolly取得百度的標題:
package main import ( "fmt" "github.com/gocolly/colly" ) func main() { c := colly.NewCollector() c.OnHTML("head", func(e *colly.HTMLElement) { title := e.ChildText("title") fmt.Println(title) }) c.Visit("http://www.baidu.com") }
beautifulsoup4go是一款基於golang的HTML解析器,與著名的Python庫BeautifulSoup4相同,可以解析來自互聯網的不同HTML頁面。以下程式碼示範如何使用beautifulsoup4go取得百度的標題:
package main import ( "fmt" "github.com/sundy-li/go_commons/crawler" ) func main() { html := crawler.FetchHTML("http://www.baidu.com", "GET", nil, "") bs := crawler.NewSoup(html) title := bs.Find("title").Text() fmt.Println(title) }
前面已經介紹過goquery函式庫,它是一個基於CSS選擇器的HTML解析器,支援鍊式操作,是一款非常實用的函式庫。以下程式碼示範如何使用goquery取得百度的標題:
package main import ( "fmt" "github.com/PuerkitoBio/goquery" "log" ) func main() { resp, err := http.Get("http://www.baidu.com") if err != nil { log.Fatal(err) } body := resp.Body defer body.Close() doc, err := goquery.NewDocumentFromReader(body) if err != nil { log.Fatal(err) } title := doc.Find("title").Text() fmt.Println(title) }
以上三個函式庫各有特色,選擇適合自己的函式庫能夠更有效率地完成爬蟲。
三、golang寫爬蟲核心技術
在實作爬蟲的過程中,一個很重要的特性就是並發,即同時訪問多個網站或多個URL。在golang中,我們可以透過協程並發地執行任務,例如:
package main import ( "fmt" "github.com/gocolly/colly" ) func main() { urls := []string{ "http://www.baidu.com", "http://www.sogou.com", "http://www.google.com", } ch := make(chan string, len(urls)) for _, url := range urls { go func(url string) { c := colly.NewCollector() c.OnHTML("head", func(e *colly.HTMLElement) { title := e.ChildText("title") ch <- title }) c.Visit(url) }(url) } for range urls { title := <-ch fmt.Println(title) } }
以上程式碼中,我們使用協程實現了並發存取多個URL,並從每個網站的head標籤中提取標題資訊並列印。
眾所周知,為了限制爬蟲的訪問,許多網站都會採取反爬蟲機制,例如限制請求頻率、添加驗證碼、識別常見爬蟲工具等。針對這些反爬蟲機制,我們需要使用一些技術方法來避免被網站封鎖。這裡介紹兩種技術手段:
(1)存取頻率控制
為了避免被網站限制存取頻率,我們可以透過設定存取間隔、採用代理IP、使用分散式方式等等手段,以避免被反爬蟲機制辨識。
例如在Gocolly框架中,我們可以使用WaitTime、RandomDelay和Limit等方法設定爬取頻率和請求限制:
package main import ( "fmt" "github.com/gocolly/colly" "time" ) func main() { c := colly.NewCollector() c.Limit(&colly.LimitRule{ DomainGlob: "*", Parallelism: 2, RandomDelay: 5 * time.Second, }) c.OnHTML("head", func(e *colly.HTMLElement) { title := e.ChildText("title") fmt.Println(title) }) c.Visit("http://www.baidu.com") }
以上程式碼中設定了並發存取數量為2,請求間隔為5秒,可以有效避免被網站限制。當然,在實際使用中,我們還需根據不同的網站設定合理的存取間隔。
(2)分散式爬取
分散式爬取可以有效地避免被網站限制,提高爬取效率。基本想法是,將不同的任務分配到不同的節點或機器上,各自獨立處理,並將結果匯總在一起。分散式爬取需要涉及調度、通訊等技術,較為複雜。在實際爬蟲中,我們可以採用第三方函式庫或雲端服務來實現分散式爬取。
結語
本文介紹如何使用golang寫爬蟲,包括基本步驟、常用函式庫和核心技術。 golang是一種具有高效能、簡潔明了的語言,能夠很好地應對爬蟲的需要。但是,在爬蟲的實踐過程中,我們還需要了解更多的技術,並且持續學習更新的反爬蟲技術,才能夠成功完成爬取任務。
以上是golang怎麼寫爬蟲的詳細內容。更多資訊請關注PHP中文網其他相關文章!