LoginSignup
24
27

More than 5 years have passed since last update.

Go言語で動的HTMLをWebスクレイピングする

Posted at

はじめに

JavaScriptで動的に生成されるWebページの場合、goqueryに直接URL渡しても正しい値でスクレイピングができない。
そのため、WebDriverを使ってブラウザに表示された実際のHTMLをgoqueryに渡してスクレイピングする必要がある。

環境

  • Ubuntu 16.04.3
  • go 1.8.3

インストール

  • ChromeDriver
# インストール
export WD_VER=2.32
wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/${WD_VER}/chromedriver_linux64.zip
sudo unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/
sudo chmod +x /usr/local/bin/chromedriver

# 確認
$ which chromedriver 
/usr/local/bin/chromedriver
  • Go パッケージ
go get github.com/PuerkitoBio/goquery
go get github.com/sclevine/agouti

流れ

ブラウザ経由でHTMLを取得

WebDriverを使用してHTMLを取得する。

url := "http://target.example.com"

driver := agouti.ChromeDriver()
err := driver.Start()
if err != nil {
    log.Printf("Failed to start driver: %v", err)
}
defer driver.Stop()

page, err := driver.NewPage(agouti.Browser("chrome"))
if err != nil {
    log.Printf("Failed to open page: %v", err)
}

err = page.Navigate(url)
if err != nil {
    log.Printf("Failed to navigate: %v", err)
}

// contentにHTMLが入る
content, err := page.HTML()
if err != nil {
    log.Printf("Failed to get html: %v", err)
}

スクレイピング

goqueryを使用してスクレイピングする。
bodyタグのaタグからhrefとコンテンツを取り出している。

  • Find()の指定方法
    • body, .container, body[class="container"]
reader := strings.NewReader(content)
doc, _ := goquery.NewDocumentFromReader(reader)
doc.Find("body a").Each(func(i int, s *goquery.Selection) {
    // bodyにコンテンツ, hrefにhrefの値が入る
    body := s.Text()
    href, _ := s.Attr("href")
    fmt.Printf("body: %s, href: %s\n", body, href)
})

実践

ブラウザで表示し、クリックしてからHTMLを取得する

クリックすると表示内容が変化する際に変化後のコンテンツをスクレイピングしたい時、ブラウザでクリック操作をした後にHTMLを取得する。

package main

import (
    "fmt"
    "log"
    "strings"

    "github.com/PuerkitoBio/goquery"
    "github.com/sclevine/agouti"
)

func main() {
    url := "http://target.example.com"

    driver := agouti.ChromeDriver()
    err := driver.Start()
    if err != nil {
        log.Printf("Failed to start driver: %v", err)
    }
    defer driver.Stop()

    page, err := driver.NewPage(agouti.Browser("chrome"))
    if err != nil {
        log.Printf("Failed to open page: %v", err)
    }

    err = page.Navigate(url)
    if err != nil {
        log.Printf("Failed to navigate: %v", err)
    }

    page.FindByButton("Next").Click()

    content, err := page.HTML()
    if err != nil {
        log.Printf("Failed to get html: %v", err)
    }

    reader := strings.NewReader(content)
    doc, _ := goquery.NewDocumentFromReader(reader)
    doc.Find("body a").Each(func(i int, s *goquery.Selection) {
        body := s.Text()
        href, _ := s.Attr("href")
        fmt.Printf("body: %s, href: %s\n", body, href)
    })
}

まとめ

動的HTMLを取得し、スクレイピングを行うことができた。
ただ、WebDriverは、ブラウザを開いて操作がされるのでただスクレイピングしたいだけだと無駄な感じがあって、実際時間がかかる。

参考

24
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
27