Protractorでスクレイピングしてみた
Railsでスクレイピングが必要な時は Nokogiri を使っていたけれど、普通のサイトはJavascriptを使っているわけで、Nokogiriだけではスクレイピングが難しいこともある。そんな時にどうしようかと。
Protractorなら、実際にユーザーがブラウザーを立ち上げて、ボタンをクリックして、テキストを読んで… みたいなことを再現できるのですごい便利。ほんとはAngular.jsのためのテストフレームワークだけど、スクレイピングにも使える。
Protractor - end to end testing for AngularJS
nvmのイントール
手元のMacOSにインストールして使ってみる。
Ruby使っているならお馴染みのrvm(Ruby Version Manager)。
nvmはNode.jsのバージョン管理ツール。
1
2
3
4
5
6
7
8
nvmを入手
$ git clone https://github.com/creationix/nvm.git ~/.nvm
リリースされているNode.jsのリスト
$ nvm ls-remote
好きなバージョンをインストール
$ nvm install v0.10.35
ターミナル起動と同時にnvmも実行させるために
~/.bash_profile を編集
1
source ~/.nvm/nvm.sh
.bash_profileを再読み込み
1
$ source ~/.bashrc
Protractorのインストール
インストールすると、
protractor と webdriver-manager というコマンドが使えるようになる。
1
2
3
4
5
6
インストール
$ npm install -g protractor
webdriver-managerをアップデート
$ webdriver-manager update
Selenium Server をスタート
1
$ webdriver-manager start
スクレイピングしてみる
用意するファイルは spec.js と conf.js だけ。
なんて簡単 :)
conf.js
javascript
1
2
3
4
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js']
};
spec.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
var url = 'http:canpath.jp';
describe('CANPATH', function() {
// For website without Angular
browser.ignoreSynchronization = true;
browser.get(url);
/*
// If you want to click something
it('should open details', function(){
// Click dropdown menu
element(by.css('.dropdown-trigger')).click().then(function(){
console.log("clicked");
})
});
*/
it('should collect title and URL from ranking', function(){
element.all(by.css('.ranking-item')).map(function(item, i){
// Collect information
// "getText" and "getAttribute" are asynchronous.
// Those action methods return a Promise. So, use then() to use the value.
var itemDate = {
url: item.element(by.xpath('.//h1[@class="title"]/a')).getAttribute('href'),
title: item.element(by.xpath('.//h1[@class="title"]/a')).getText()
};
// Array will be returned.
return itemDate;
}).then(function(menu){
// Show this array in terminal
console.log(menu);
console.log("Done!");
}); //
}); //it
}); //describe
実行結果
実行結果はこんな感じ。
http://canpath.jp の人気ストーリーランキングを取ってみました。
実際にブラウザーが立ち上がって、スクレイピングが行われます。
shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$ protractor conf.js
Using the selenium server at http://localhost:4444/wd/hub
[launcher] Running 1 instances of WebDriver
[ { url: 'http://www.canpath.jp/stories/23',
title: '立ち直るきっかけを作ってくれた セブ島に感謝' },
{ url: 'http://www.canpath.jp/stories/49',
title: '就職より大事なもの。そうだセブ島にいこう!' },
{ url: 'http://www.canpath.jp/stories/298',
title: 'Can you follow me?' },
{ url: 'http://www.canpath.jp/stories/55', title: '私の大きな転機。' },
{ url: 'http://www.canpath.jp/stories/277',
title: 'トビタテ!留学JAPAN1期生の1人として思うことを改めて。' },
{ url: 'http://www.canpath.jp/stories/6',
title: 'NZに家族で移住しちゃおう!' },
{ url: 'http://www.canpath.jp/stories/304',
title: 'Happy birthday from all over the world' },
{ url: 'http://www.canpath.jp/stories/46',
title: 'タイで起業中に起きたこと。思ったこと。' },
{ url: 'http://www.canpath.jp/stories/299',
title: '寝ても覚めても、海外' },
{ url: 'http://www.canpath.jp/stories/51',
title: 'カナダで気づいた“言葉の先にあったもの”' },
{ url: 'http://www.canpath.jp/stories/316', title: '6歳の女の子の話。' },
{ url: 'http://www.canpath.jp/stories/321',
title: 'To be someone' },
{ url: 'http://www.canpath.jp/stories/8', title: '海外でウェブサイト受注' },
{ url: 'http://www.canpath.jp/stories/4',
title: '自由な生き方を教えてくれたオーストラリアの冒険家' },
{ url: 'http://www.canpath.jp/stories/53',
title: 'スイスの山に登ってきました' } ]
Done!
.
Finished in 9.837 seconds
1 test, 0 assertions, 0 failures
今日の日付のディレクトリを自動生成して、
テキストファイルに保存するという流れで実用できそうです。
それもNode.jsでできるよ。
やってから思ったけど、PhantomJSだけでいいかもな…。
参考
Protractor - end to end testing for AngularJS
まだmechanizeで消耗してるの? WebDriverで銀行をスクレイピング(ProtractorとWebdriverIOを例に) - 詩と創作・思索のひろば
protractor-scrape-money/mufg.js at master · motemen/protractor-scrape-money
mkdirp - node.jsで連続フォルダ作成パッケージ | Node.js技術
Node.js Error: Cannot find module express - Stack Overflow
node.js - NPM global install "cannot find module" - Stack Overflow