Golang + Chrome on CentOS7(Docker)でスクレイピング

## 概要
Golangとchromeを使って、CentOS7上でスクレイピングをする環境を構築します。
Dockerで環境を構築します。

python版は、こちらです。
[Python + Chrome on CentOS7(Docker)でスクレイピング](https://qiita.com/Esfahan/items/0071acc11377ae3f4e4a)

## 関連記事
- [docker(docker-engine), docker-composeのインストール](https://qiita.com/Esfahan/items/aa5802548ee42d8a98de)
- [Dockerコマンド よく使うやつ](https://qiita.com/Esfahan/items/52141a2ad741933d7d4c)
- [Python + PhantomJSでスクレイピング](https://qiita.com/Esfahan/items/4655a954e8e7e7c557a4)

## 環境構築
以下の内容はGitHubにpushしてあるので、こちらをcloneしていただいてDockerを起動させれば実現できます。
https://github.com/Esfahan/docker-go-chrome

## ディレクトリ構成
以下のディレクトリ構成を前提とします。
/codeは、dockerコンテナにマウントさせる領域です。

```
code/
Dockerfile
files/
```

### google-chrome.repo
google-chromeを取得するためのレポジトリファイルを作成します。
files/etc/yum.repos.d/google-chrome.repoとして作成します。

```ini
[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
```

### Dockerfileを作成

```Dockerfile
From centos:7

ARG GO_VER=1.11
ARG CHROME_DRIVER_VER=2.43

RUN yum update -y

########
# go
########
WORKDIR /usr/local/src
RUN yum install -y git
RUN curl -O https://dl.google.com/go/go${GO_VER}.linux-amd64.tar.gz
RUN tar -C /usr/local -xzf go${GO_VER}.linux-amd64.tar.gz

ENV GOPATH=/code
ENV PATH=$PATH:$GOPATH/bin
ENV PATH=$PATH:/usr/local/go/bin


########################
# chromedriver, chrome
########################
# chromedriver
RUN yum install -y unzip
RUN curl -O https://chromedriver.storage.googleapis.com/${CHROME_DRIVER_VER}/chromedriver_linux64.zip
RUN unzip chromedriver_linux64.zip
RUN mv chromedriver /usr/local/bin/

# Dependencies
RUN yum install -y libX11 \
                   GConf2 \
                   fontconfig

# chrome
ADD files/etc/yum.repos.d/google-chrome.repo /etc/yum.repos.d/google-chrome.repo
RUN yum install -y google-chrome-stable \
                   libOSMesa

# fonts
RUN yum install -y google-noto-cjk-fonts \
                   ipa-gothic-fonts
```

### build

```
$ docker build -t go-chrome:latest ./
```

### コンテナ起動

```
$ docker run --name go-chrome-container \
             -v $(pwd)/code:/code \
             -itd go-chrome:latest /bin/bash
```

## 初期設定
### プロジェクトルートディレクトリを作成

```shell-session
$ mkdir -p code/src/prj/
```

### depをインストール

```shell-session
$ docker exec -it go-chrome-container /bin/bash -c 'go get -u github.com/golang/dep/cmd/dep'
```

ディレクトリが色々作成されたことを確認

```shell-session
$ docker exec -ti go-chrome-container /bin/bash -c 'ls /code/*'
/code/bin:
dep

/code/pkg:
dep

/code/src:
github.com  prj
```

### dep init

```
$ docker exec -it go-chrome-container /bin/bash -c 'cd /code/src/prj/ && dep init'
```

ファイルが色々作成されたことを確認

```shell-session
$ docker exec -ti go-chrome-container /bin/bash -c 'ls /code/src/prj'
Gopkg.lock  Gopkg.toml  vendor
```

## Golangのスクリプトを作成

/code/src/prj/main.go

```go
package main

import (
	"github.com/PuerkitoBio/goquery"
	"github.com/sclevine/agouti"
	"log"
	"strings"
)

func main() {
	driver := agouti.ChromeDriver(
		agouti.ChromeOptions("args", []string{
			"--headless",
			"--disable-gpu",
			"--window-size=1280,1024",
			"--disable-dev-shm-usage",
			"--no-sandbox",
		}),
		agouti.Debug,
	)

	if err := driver.Start(); 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)
	}

	// Access to a target page
	url := "https://www.google.co.jp/"
	err = page.Navigate(url)
	if err != nil {
		log.Printf("Failed to navigate: %v", err)
	}

	// Wait for a DOM element to exist
	page.Session().SetImplicitWait(30)

	// Get screen shot
	page.Screenshot("Google.png")

	// Get title
	title, err := page.Title()
	if err != nil {
		log.Printf("Failed to get Title: %v", err)
	}
	log.Printf(title)

	// Get current url
	current_url, err := page.URL()
	if err != nil {
		log.Printf("Failed to get current url: %v", err)
	}
	log.Printf(current_url)

	// Get HTML
	getSource, err := page.HTML()
	//log.Printf(getSource)
	if err != nil {
		log.Fatalf("Failed to get HTML:%v", err)
	}

	// Parse DOM
	readerCurContents := strings.NewReader(getSource)
	doc, err := goquery.NewDocumentFromReader(readerCurContents)
	if err != nil {
		log.Fatal(err)
	}

	// Get title from DOM
	log.Printf(doc.Find("title").Text())
}
```

## 必要なモジュールをインストール

```shell-session
$ docker exec -it go-chrome-container /bin/bash -c 'cd /code/src/prj && dep ensure'
```

## 実行
これを実行すると、Googleのトップページのtitleである`Google`が表示され、Google.pngとして、スクリーンショットが作成されます。

```shell-session
$ docker exec -it go-chrome-container /bin/bash -c 'cd /code/src/prj && go run main.go'
Starting ChromeDriver 2.43.600233 (523efee95e3d68b8719b3a1c83051aa63aa6b10d) on port 42712
Only local connections are allowed.
2018/11/01 09:30:53 Google
2018/11/01 09:30:53 https://www.google.co.jp/
2018/11/01 09:30:53 Google
```


`Prevent Error: Fontconfig warning: "/etc/fonts/fonts.conf", line 86: unknown element "blank"`というエラーが出る場合は、/etc/fonts/fonts.confの、`<blank>`と`</blank>`の削除、もしくはコメントアウトをして下さい。

参考：[発生したエラーについて](https://qiita.com/aibax/items/fade7e417f6c096a879b#%E7%99%BA%E7%94%9F%E3%81%97%E3%81%9F%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)