CollyはGo言語でWebスクレイピングを行うためのライブラリです。
Elegant Scraper and Crawler Framework for Golang
以下にCollyの使い方を紹介します。
インストール #
go modコマンドでgo.modファイルを作成し、go getでcollyを導入します。
go mod init colly-scraping-test
go get github.com/gocolly/colly/v2
collyの基本的な使用方法 #
Collyを使用してスクレイピングを行うには以下のような流れで処理を行います。
- colly.NewCollector関数で新しいCollectorを作成する
- CollectorのOnHTMLメソッドやOnResponseメソッドを使用してCollectorの動作を定義する
- Visitメソッドでスクレイピングを開始する
例として、このブログのトップページのプロフィール部分のプロフィール画像URLとプロフィール名を取得してみます。
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
func main() {
c := colly.NewCollector()
var profileImageURL string
c.OnHTML("#main-content img", func(e *colly.HTMLElement) {
profileImageURL = e.Attr("src")
})
var profileName string
c.OnHTML("#main-content h1", func(e *colly.HTMLElement) {
profileName = e.Text
})
err := c.Visit("https://kazusa-pg.com/")
if err != nil {
panic(err)
}
fmt.Println(profileImageURL)
fmt.Println(profileName)
}
このコードは実行するとプロフィール画像のsrcとプロフィール名が表示されます。
/img/profile-picture_hu2961160223197158946.png
かずさプログラマー
collectorのOnHTMLメソッドにはセレクター要素ごとに動作を定義できるので今回のコードでは以下の2つの動作を設定しています。
#main-content img
のセレクター要素でsrc属性をprofileImageURL変数に格納する#main-content h1
のセレクター要素のテキストをprofileName変数に格納する
リンク先のページの情報を取得する #
Collyを使用すると指定したページに表示されている各リンクをたどって、リンク先のページの情報を取得することができます。
このブログのトップページに表示されている最新の記事10件にアクセスして、各記事のタイトルと何分で読了できるかの情報を取得してみます。
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
// 参考URL:https://github.com/gocolly/colly/blob/master/_examples/coursera_courses/coursera_courses.go
type pageDetail struct {
title string
readTime string
}
func main() {
pageDetails := []pageDetail{}
c := colly.NewCollector(
colly.AllowedDomains("kazusa-pg.com"),
)
detailCollector := c.Clone()
c.OnHTML("section.w-full > a", func(e *colly.HTMLElement) {
absoluteURL := e.Request.AbsoluteURL(e.Attr("href"))
detailCollector.Visit(absoluteURL)
})
detailCollector.OnRequest(func(r *colly.Request) {
fmt.Println("visiting", r.URL.String())
})
detailCollector.OnHTML("#single_header", func(e *colly.HTMLElement) {
pd := pageDetail{
title: e.ChildText("h1"),
readTime: e.ChildText("span[title]"),
}
pageDetails = append(pageDetails, pd)
})
c.Visit("https://kazusa-pg.com/")
for _, pd := range pageDetails {
fmt.Printf("%s %s\n", pd.title, pd.readTime)
}
}
コードを実行すると各ブログのURLにアクセスし、リンク先のタイトルと何分で読了できるかの情報を表示します。
visiting https://kazusa-pg.com/neetcode-arrays-and-hashing/
visiting https://kazusa-pg.com/golang-jpeg-progressive/
visiting https://kazusa-pg.com/pq-next-business-day/
visiting https://kazusa-pg.com/playwright-go-upload-file/
visiting https://kazusa-pg.com/golang-add-shape-frame/
visiting https://kazusa-pg.com/vba-copy-shapes/
visiting https://kazusa-pg.com/wp-to-hugo/
visiting https://kazusa-pg.com/golang-get-files-in-zip/
visiting https://kazusa-pg.com/vba-get-files-in-zip/
visiting https://kazusa-pg.com/golang-colly-web-scraping/
【Golang】NeetCodeのArrays & Hashingを解く 5 分
【Golang】jpeg画像がプログレッシブ形式か判別する 2 分
【Power Query】Excel Power Queryで翌営業日・前営業日を出力する 4 分
【Golang】playwright-goでファイルをアップロードする 3 分
【Golang】png画像に枠線をつける 1 分
【VBA】図形を別シートにコピーする 1 分
WordPressからHugoに移行しました 10 分
【Golang】zip内のファイル一覧を展開せずに取得する 2 分
【VBA】zip内のファイル一覧を展開せずに取得する 2 分
【Golang】Collyを使用してWebスクレイピングを行う 5 分
ファイルや画像を保存する #
Collyを使って画像をダウンロードして保存するにはcollectorのOnResponseメソッドを使用します。
OnResponseはサーバーからレスポンスを受け取るたびに呼び出されます。
レスポンスにはサーバーから返されたHTMLや画像などのコンテンツが含まれているのでSaveメソッドを使用することでレスポンスの内容を保存することができます。
下記のコードは、このブログのトップページのプロフィール画像を保存するサンプルです。
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
func main() {
c := colly.NewCollector()
c.OnResponse(func(r *colly.Response) {
r.Save("./profile.png")
fmt.Print("保存しました")
})
err := c.Visit("https://kazusa-pg.com/img/profile-picture_hu2961160223197158946.png")
if err != nil {
panic(err)
}
}
コードを実行すると、コードを実行したパスに、このブログのプロフィール画像をprofile.pngとして保存します。
エラーを処理する #
Collyを使ってWebスクレイピングを行う際にエラーが発生することがあります。
例えばサーバーから404エラーが返されたり、タイムアウトしたりすることがあります。
Collyではエラーを処理するためにOnErrorメソッドが用意されています。
このメソッドを設定することで、エラーが発生したときの動作を定義することができます。
下記のコードではテストサーバーから404 Not Foundが返ってくるのでOnErrorメソッドを使ってエラーを処理しています。
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/gocolly/colly/v2"
)
func main() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
defer server.Close()
c := colly.NewCollector()
c.OnError(func(r *colly.Response, err error) {
fmt.Println("エラーが発生しました:", err)
})
c.Visit(server.URL)
}
コードを実行すると下記のように表示されます。
エラーが発生しました: Not Found
もしくはVisitメソッドがerrorを返すので、errorの内容を元に処理を行います。
err := c.Visit("URL")
if err != nil {
panic(err)
}