Help us understand the problem. What is going on with this article?

Goとgoqueryでスクレイピング

More than 1 year has passed since last update.

一億番煎じ:tea:記事でございます:pensive:
最近一億番煎じというフレーズがマイブームになりつつある:raised_hands:
自分の整理のための記事ですが、コメントとかいいねしてくれたら泣いて喜びます:joy:

公式
https://github.com/PuerkitoBio/goquery
GoDoc
https://godoc.org/github.com/PuerkitoBio/goquery

概要とかインストールとか

公式Githubに書いてあるとおりですが、jQuery的にスクレイピングやクローリングができるライブラリです。
インストールはgetで。glideを使いたければそれでも。

$ go get github.com/PuerkitoBio/goquery

ドキュメントを取得

なにはともかくドキュメントを取得しましょう。

Getで取得

ごく普通のページはfunc NewDocument(url string) (*Document, error)を使います。

NewDocumentを使う
doc, err := goquery.NewDocument("対象のURL")
if err != nil {
    panic(err)
}

これで対象のURLからGetでドキュメントを取得してくれます。

Postなどリスエストをカスタマイズして取得

ページによってはPostパラメータを付けなければならないとか、リクエストヘッダーを弄りたいということがあります。
その場合は、まずnet/httpnet/urlを使ってレスポンスを取得し、それをfunc NewDocumentFromResponse(res *http.Response) (*Document, error)に渡してやります。

NewDocumentFromResponseを使う
// パラメータを作る
values := url.Values{}
values.Add("key", "value")
...

// リクエストを作る
// 例えばPOSTでパラメータつけてUser-Agentを指定する
req, err := http.NewRequest("POST", "対象のURL", strings.NewReader(values.Encode())) 
if err != nil {
    panic(err)
}
req.Header.Add("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1")

// リスエスト投げてレスポンスを得る
client := &http.Client{}
resp, err := client.Do(req)

// レスポンスをNewDocumentFromResponseに渡してドキュメントを得る
doc, err := goquery.NewDocumentFromResponse(resp)
if err != nil {
    panic(err)
}

ここらへんgoqueryはサポートしてないんだなーと思ったりもしましたが、下手にサポートして制限があるよりかは一切手を出さないから好きにやってね、の方がいいような気もします。

Readerから取得

あんまり頻繁にページアクセスするのは申し訳ないと思うときは、一旦HTMLをローカルにダウンロードし、ローカルのHTMLからfunc NewDocumentFromReader(r io.Reader) (*Document, error)でドキュメントを取得することもできます。

Readerを使う
fileInfos, _ := ioutil.ReadFile("HTMLのファイルパス")
stringReader := strings.NewReader(string(fileInfos))
doc, err := goquery.NewDocumentFromReader(stringReader)
if err != nil {
    panic(err)
}

セレクションを取得

ドキュメントが取得できたら、そこからほしいデータがあるタグをなり塊なりをfunc (s *Selection) Find(selector string) *Selectionで取得しましょう。
Findはドキュメントに対してもセレクションに対しても使えます。
セレクタについては↓らへんを見たらいいんじゃないでしょうか(雑)
セレクタの種類

Findでセレクタを取得
// ドキュメントから
selection := doc.Find("div#some_id > div.some_class")

// セレクションから更にセレクションを取得
innerSeceltion := selection.Find("a")

// セレクションが複数ある場合はEachで回せます
innerSeceltion.Each(func(index int, s *goquery.Selection) {
    // なんかする
})

セレクションをたどる

以下などがあります。一通りできますね!(雑)
func (s *Selection) Children() *Selection
func (s *Selection) First() *Selection
func (s *Selection) Last() *Selection
func (s *Selection) Next() *Selection
func (s *Selection) Parent() *Selection
func (s *Selection) Prev() *Selection
func (s *Selection) Siblings() *Selection

データを抜く

目的のセレクションに到達したら、ほしいデータを抜き取りましょう。
以下が使えそうな関数です。
func (s *Selection) Attr(attrName string) (val string, exists bool)
func (s *Selection) AttrOr(attrName, defaultValue string) string
func (s *Selection) Html() (ret string, e error)
func (s *Selection) Text() string

データを抜く
// セレクションより下のタグ入りの文字列を取得
html, err := selection.Html()

// セレクションより下の全てのテキストを取得
text := selection.Text()

// 属性を取得、existsはその属性が存在するか
attr, exists := selection.Attr("href")

// 属性が存在しない場合はdefaultValueを返す
attrWithDefault := selection.AttrOr("src", "default")

おわりに

~queryがたくさんありますが、どれか一つ覚えておけば言語が変わっても使えるという安心感があります:blossom:
Goは始めたばかりですが、goqueryに関してはあまり詰まること無く使えました:confetti_ball:
この記事では扱ってないですが、ノードやクラスを追加したりもできるみたいだし、あるHTMLを元に別のHTMLを生成するみたいなこともできそうですね:eyes:

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした