Ubuntu Server15.04でnode.jsによるスクレイピング環境を整える

#目的
* Ubuntu Server 15.04でGoogleから検索結果を取得する
* 検索結果のキャプチャもとる
* **ただしUbuntu Serverはインストール済みのものとする。**


#開発ツール一式他のInstall

```bash
$ sudo aptitude install build-essential freetype fontconfig python
```
build-essentialはこれがないと始まらない。freetypeとfontconfigは後々必要になる。

#nodeのversion管理システムを入れる
nodeのversion管理にはnodebrewやらnvmやらnodeenvやらあるけど凄く入れやすいnodebrewにすることにした。

```bash
$ curl -L git.io/nodebrew | perl - setup
$ echo export PATH=$HOME/.nodebrew/current/bin:$PATH >> ~/.bashrc
$ source ~/.bashrc
```

```bash
$ nodebrew help
nodebrew 0.9.2

Usage:
    nodebrew help                         Show this message
    nodebrew install <version>            Download and install a <version> (compile from source)
    nodebrew install-binary <version>     Download and install a <version> (binary file)
    nodebrew uninstall <version>          Uninstall a version
    nodebrew use <version>                Use <version>
    nodebrew list                         List installed versions
    nodebrew ls                           Alias for `list`
    nodebrew ls-remote                    List remote versions
    nodebrew ls-all                       List remote and installed versions
    nodebrew alias <key> <version>        Set alias to version
    nodebrew unalias <key>                Remove alias
    nodebrew clean <version> | all        Remove source file
    nodebrew selfupdate                   Update nodebrew
    nodebrew migrate-package <version>    Install global NPM packages contained in <version> to current version
    nodebrew exec <version> -- <command>  Execute <command> specified <version>

Example:
    # install from binary
    nodebrew install-binary v0.10.22

    # use a specific version number
    nodebrew use v0.10.22

    # io.js
    nodebrew install-binary io@v1.0.0
    nodebrew use io@v1.0.0
```

#nodeを入れる
現在の安定版は[公式サイト](https://nodejs.org/en/)によるとv5.1.0らしい。とりあえず何も考えず入れてみよう、ライブラリとか動かなくてversion下げる事はあるかもしれない。

```bash
$ nodebrew install-binary v5.1.0
$ nodebrew use v5.1.0
$ node -v
v5.1.0
```
いつのversionからかはわからないがnodeを入れるとnpmも自動で入るのでガリガリ入れていく。その前に適当なワークディレクトリでも作ろう。


#work directoryを作る
汚すかもしれないので移動

```bash
$ mkdir -p work/ScrapeSample && cd $_
```

#npmを初期化する
ノードのバージョン管理するならモジュールもちゃんとバージョン管理しましょうね。ってことでinit
まぁモジュールはいれないけどね…。

```bash
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (ScrapeSample) 
Sorry, name can no longer contain capital letters.
name: (ScrapeSample) 
Sorry, name can no longer contain capital letters.
name: (ScrapeSample) scrape
version: (1.0.0) 
description: 
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: 
license: (ISC) 
About to write to /home/molt/work/ScrapeSample/package.json:

{
  "name": "scrape",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes) 

```
Enterをぽんぽん押せばおｋ、と思ってたら名前長過ぎるから短くしろと怒られました。

###2016/08/16追記
コメントにてご指摘。ありがてぇ

```
name: (ScrapeSample) 
Sorry, name can no longer contain capital letters.

というエラーですが、「名前長過ぎるから短くしろと怒られました。」ということではなく、「もはや名前に大文字を含めることはできません。」というエラーと思われます。
```

どうみても`no longer`です。本当にありがとうございました。
「今時名前に大文字いれてるんじゃねーよ！」的なノリだろうか…。

#スクレイピングのためのモジュールを入れる
nodejsでのスクレイピングは`cheerio-httpcli`を使うのが鉄板。しかし動的なサイトも当然ある世の中はブラウザのオートメーションという切り口でスクレイピングをしていったほうが良いように思う。
スクショも撮りたいかもしれないし…。なので`phantomjs`をチョイスします。あと`phantomjs`のラッパーである`casperjs`も。
ココらへんもしかしたらProtractorのが良いのかもしれない。でもJavaはいれたくないんだ。他に何か良いライブラリあったら教えて下さい。`casperjs`はコールバック地獄になるとかいうエントリもあるけど昔の話だよねぇ？
```
$ npm i -S -g phantomjs casperjs
```

#ソースを書く
テストがてらキャプチャーを取得するコードを書く。CasperJsはCoffeeScriptをそのまま認識してくれるが今回はJavaScriptで書きます。

```bash
$ mkdir src
$ nano src/google.js
```

```js
#!/usr/bin/env node

'use strict';

var target = 'http://google.co.jp';

var casper = require('casper').create();

casper.options.waitTimeout = 1000;
casper.start();
casper.viewport(1440,900);

casper.open(target);

casper.then(function(){
  this.capture('cap.png');
});

casper.run();
```

```
$ casperjs src/google.js
```
でき…ん？？？

結果
![google.png](https://qiita-image-store.s3.amazonaws.com/0/35278/9afdf262-ffbd-d3f3-a700-a0cc6d61f917.png)

#豆腐問題を解決する

参考：http://t-cyrill.hatenablog.jp/entry/2014/10/05/123803

日本語のフォントが入ってないので豆腐になりますよってことだ。
記事中ではversionの問題とあるけどUbuntuではversion変えてもだめだったので素直に日本語フォントを入れる。ちなみに別の記事では2.0.x系にあげれば解決するとか書いてあったんだが、公式サイトを見ながらBuildしようとしても失敗してしまったので1.9.8で進める…。

```bash
$ sudo aptitude install fonts-migmix
$ sudo nano /etc/fonts/local.conf
```

/etc/fonts/local.conf

```xml
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <match target="pattern">
    <test qual="any" name="family">
      <string>serif</string>
    </test>
    <edit name="family" mode="assign" binding="strong">
      <string>MigMix 2P</string>
    </edit>
  </match>
</fontconfig>
```

できました。
![google.png](https://qiita-image-store.s3.amazonaws.com/0/35278/364e110f-c85b-0cf5-6f3a-514cf6d7bd55.png)


あとは[QuickStart](http://docs.casperjs.org/en/latest/quickstart.html)を参考にリンクを取得する処理を書いていく。

```js
#!/usr/bin/env node

'use strict';

function getLinks() {
    var links = document.querySelectorAll('h3.r a');
    return Array.prototype.map.call(links, function(e) {
        return e.getAttribute('href');
    });
}


var word = 'Qiita';
var target = 'http://google.co.jp';

var casper = require('casper').create();
var links = [];
casper.options.waitTimeout = 1000;
casper.start();
casper.viewport(1440,900);

casper.open(target);
casper.then(function(){
  this.capture('google.png');
});

casper.then(function(){
  links = this.evaluate(getLinks);
  // 第一引数で対象のフォーム、第二引数でパラメータ、第三引数で入力後submitするか
  this.fill('form[action="/search"]', { q: word }, true);
});
casper.then(function() {
  this.capture('cap.png');
  // aggregate results for the 'phantomjs' search
  links = links.concat(this.evaluate(getLinks));
});

casper.run(function(){
  this.echo(links.length + ' links found:');
  this.echo(' - ' + links.join('\n - ')).exit();
});
```


#結果
お疲れ様でした。
![cap.png](https://qiita-image-store.s3.amazonaws.com/0/35278/e17a7034-6efc-9fd5-5687-932eb4094298.png)

```
$ casperjs src/google.js 
13 links found:
 - /url?q=https://qiita.com/&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QFggVMAA&usg=AFQjCNHu2rYnJu2kROQRZoO_pGa7aWxJhQ
 - /url?q=http://qiita.com/tags&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QjBAIHDAB&usg=AFQjCNHAmSmV_E0SGT2hkBwq9CJmmBD3mg
 - /url?q=https://teams.qiita.com/&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QjBAIHjAE&usg=AFQjCNEgQ_0ofyj5c1kqVRrGtim4qZezlQ
 - /url?q=https://qiita.com/about&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QjBAIIDAC&usg=AFQjCNGlrUpC-22zqE4QsslqlROgRFVRqg
 - /url?q=https://qiita.com/advent-calendar/2015&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QjBAIIjAF&usg=AFQjCNGfkNYqSumMEhIxzHagMgeAcCK0fQ
 - /url?q=http://qiita.com/advent-calendar&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QjBAIJDAD&usg=AFQjCNGwyDgbWOn4b57KPhfVLNKG_77VaQ
 - /url?q=http://kobito.qiita.com/&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QjBAIJjAG&usg=AFQjCNFN5t0GHo7wyt1UuUCGQcYFzcX99g
 - /url?q=https://twitter.com/qiita&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QFggoMAc&usg=AFQjCNGaTozeV5-fncLLq17MkKGvr37lDg
 - /url?q=http://anond.hatelabo.jp/20150127003906&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QFgguMAg&usg=AFQjCNHhQiAuVPxZVrBqIhbKHhpitpbM_g
 - /search?q=Qiita&hl=ja&gbv=2&prmd=ivns&source=univ&tbm=nws&tbo=u&sa=X&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QqAIINQ
 - /url?q=https://ferret-plus.com/1856&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QFgg7MAs&usg=AFQjCNH0CxsyNTGFZWCd6hfdCcHDwsbcxQ
 - /url?q=http://hrnabi.com/2015/03/11/6001/&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QFghBMAw&usg=AFQjCNEO3eju-tqSvW2-ZP3FGBhba7Maww
 - /url?q=http://qrank.wbsrv.net/&sa=U&ved=0ahUKEwil9a65g8XJAhUCGpQKHb5HCo8QFghHMA0&usg=AFQjCNFQ4Oy_40Cxx2Z1mkFdS-FUfhuG0A

```