Go言語(golang)のAgouti(Selenium WebDriver)の使い方
Go言語でSelenium WebDriverを使うサードパーティパッケージAgoutiの使い方。
Webブラウザを自動化し、作成したウェブサイトのテストやウェブクローラーに使います。
ライブラリのAgoutiの他、Google Chromeを使う場合は、chromedriver が FireFoxを使う場合は、geckodriverが必要になるので、
ダウンロード、解凍して、パスの通った場所に配置するか capabilities の binary にパスを指定します。
AgoutiのGitHubページ
Agoutiの godocページ
Seleniumのドキュメントページ
Chromeのドライバーとドキュメント
- chromeのドライバーダウンロードページ
- chrome driverのドキュメント
FireFoxのドライバーとドキュメント
geckodriverのダウンロードページ
gecko driverのGitHubページ
firefoxのコマンドラインオプション
目次
- パッケージのダウンロード
- 基本的な使い方
- ヘッドレスモードで起動(ブラウザを非表示する)
- ブラウザのプロフィールを指定する
- 拡張機能を使う
- JavaScript を実行する
- Google-Chrome のオプション
- FireFox のオプション
パッケージのダウンロード
$ go get github.com/sclevine/agouti
基本的な使い方
example.com
にアクセスしてタイトルを表示
package main import ( "fmt" "os" "github.com/sclevine/agouti" ) func main() { driver := agouti.ChromeDriver() defer driver.Stop() if err := driver.Start(); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) return } page, err := driver.NewPage() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) return } page.Navigate("https://example.com") fmt.Println(page.Title()) }
ヘッドレスモードで起動(ブラウザを非表示する)
chromeのオプション(引数)に --headless を指定します。
ヘッドレス Chrome ことはじめ https://developers.google.com/web/updates/2017/04/headless-chrome
package main import ( "fmt" "os" "github.com/sclevine/agouti" ) func main() { options := agouti.ChromeOptions( "args", []string{ "--headless", "--disable-gpu", // 暫定的に必要らしいです。 }) driver := agouti.ChromeDriver(options) defer driver.Stop() driver.Start() page, err := driver.NewPage() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) return } page.Navigate("https://example.com") fmt.Println(page.Title()) }
ブラウザのプロフィールを指定する
何も指定しない場合は、一時的な新しいプロフィールが使われるので、
--user-data-dir
でパスを指定すれば、そのプロファイル(パスになければ作成されます)が使用されます。
package main import ( "fmt" "os" "github.com/sclevine/agouti" ) func main() { options := agouti.ChromeOptions( "args", []string{ "--user-data-dir=/path/to/profile", }) driver := agouti.ChromeDriver(options) defer driver.Stop() driver.Start() page, err := driver.NewPage() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) return } page.Navigate("https://example.com") fmt.Println(page.Title()) }
拡張機能を使う
GoogleChromeの拡張機能を使う。ただし、ヘッドレスでは組み込めないので、
予めプロファイルを作成し、そこに拡張機能をインストールする必要があります。
package main import ( "fmt" "io/ioutil" "os" "github.com/sclevine/agouti" ) func main() { crxBytes, _ := ioutil.ReadFile("/path/to/extension.crx") options := []agouti.Option{ agouti.ChromeOptions( "args", []string{ "--user-data-dir=/path/to/profile", }), agouti.ChromeOptions("extensions", [][]byte{crxBytes}), } driver := agouti.ChromeDriver(options...) defer driver.Stop() driver.Start() page, err := driver.NewPage() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) return } page.Navigate("https://example.com") fmt.Println(page.Title()) }
JavaScript を実行する
package main import ( "fmt" "net/http" "github.com/sclevine/agouti" ) func main() { var options []agouti.Option client := new(http.Client) // httpクライアントを設定する(設定していない場合は、内部的にhttp.DefaultClientが使われる) options = append(options, agouti.HTTPClient(client)) // なんのタイムアウトなのかわかりません。 options = append(options, agouti.Timeout(190)) // seconds // SSL証明書が無効な場合は拒否する(デフォルトではすべて受け入れる) options = append(options, agouti.RejectInvalidSSL) capabilities := agouti.Capabilities{ "args": []string{ "--disable-gpu", "--headless", }, } options = append(options, agouti.Desired(capabilities)) driverPath := "/usr/local/bin/chromedriver" command := []string{driverPath, "--port={{.Port}}"} driver := agouti.NewWebDriver("http://{{.Address}}", command, options...) driver.Start() defer driver.Stop() // page ごとにオプションを変更する場合は以下のように NewPage に指定する page, err := driver.NewPage(options...) if err != nil { fmt.Println(err) return } // ポップアップの無効化 if err := page.CancelPopup(); err != nil { fmt.Println(err) } // ページロードのタイムアウト(秒) if err := page.SetPageLoad(90); err != nil { fmt.Println(err) } // すぐに取得できない要素を待つ(秒) if err := page.SetImplicitWait(10); err != nil { fmt.Println(err) } if err := page.Navigate("https://example.com"); err != nil { fmt.Println(err) return } // JavaScriptを実行する javascript := `document.body.innerHTML = element; return "hello"` // スクリプト内で使う変数 variables := map[string]interface{}{ "element": interface{}("<h1>hello</h1>"), } // return で返ってくる値を受け取る var result string if err = page.RunScript(javascript, variables, &result); err != nil { fmt.Println(err) } else { fmt.Println(result) // hello } }
Google-Chrome のオプション
ChromeOptions の一覧は以下に載ってます。 https://sites.google.com/a/chromium.org/chromedriver/capabilities
package main import ( "fmt" "os" "github.com/sclevine/agouti" ) func main() { driver := agouti.ChromeDriver( agouti.Browser("chrome"), agouti.Debug, agouti.ChromeOptions("prefs", map[string]interface{}{ "download.directory_upgrade": true, "download.default_directory": "/home/xxx/Downloads", // ダウンロードするディレクトリ "download.prompt_for_download": false, "plugins.always_open_pdf_externally": true, "plugins.plugins_disabled": "Chrome PDF Viewer", "profile.default_content_settings.popups": 0, }), agouti.ChromeOptions("args", []string{ "--disable-gpu", "--headless", "--start-maximized", // ブラウザのサイズを指定する }), ) if err := driver.Start(); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } defer driver.Stop() page, err := driver.NewPage() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) return } page.Navigate("https://example.com") fmt.Println(page.Title()) }
FireFox のオプション
Socks5プロキシを使って接続する
package main import ( "fmt" "os" "github.com/sclevine/agouti" ) func main() { options := []agouti.Option{ agouti.Browser("firefox"), } capabilities := agouti.Capabilities{ "moz:firefoxOptions": map[string]interface{}{ "args": []string{ "--headless", }, "prefs": map[string]interface{}{ "network.proxy.type": 1, "network.proxy.socks": "127.0.0.1", "network.proxy.socks_port": 9050, }, }, } driver := agouti.GeckoDriver(append(options, agouti.Desired(capabilities))...) if err := driver.Start(); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } defer driver.Stop() page, err := driver.NewPage() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) return } page.Navigate("https://check.torproject.org/") fmt.Println(page.Title()) }