【在庫一掃処分セール2015】
とりあえず記事を書き始めたものの途中で何らかの理由でモチベーションが下がり放置されていた記事を掘り起こして、なんとか続きを書き切ることで 2015年に悔いを残さず新年を迎えようという企画です
この記事の途中でモチベーションが落ちた主な原因
- 文章のテンションの方向性を見失った
- この内容に興味がある人が皆無に思えた
さあ、そんな理由でボツになりかけていた記事をお楽しみください
誰でも1度は モテたいなーと思いますよね?
そんなときふと思いました
「Webサイトをクロールしたらモテそうだなー」と
そこで、今回は確実にモテる Web サイトクローリング & スクレイピングのやり方を皆さんにご紹介します
そもそも "クローリング"、"スクレイピング" って何?というあなた
クローリングもしくはスクレイピングとは、お目当の Web サイトにアクセスして情報を抽出することを言います
※正式にはクローリングとスクレイピングには区別があるらしいです
どうです、何だかモテそうでしょう?
この記事では
1. なぜモテる Web サイトクローリングが求められているのか
2. モテるのはどんな方法なのか
3. PhantomJS & cheerio の最強タッグ
4. クローラーの実装方法
5. PhantomJS の よくある質問
6. クローリングは慎重に!
7. まとめ
について説明します
1. なぜモテる Web サイトクローリングが求められているのか
さて、モテる Web サイトクローリングのやり方を紹介する前に、なぜ今までのクロールではモテないのかを考える必要があります
まずは、これまでに僕がトライしてきたモテないクローリングの歴史をご紹介します
なぜ今までの方法がモテないのか、どうすればモテるのかを紐解いて行きましょう
クローリング 1.0 時代
まず最初にクローリングでモテようとして思いつくのは、手動で Web ブラウザからサイトにアクセスして目視で情報を探して抜き出す方法です
特に知識がなくても誰でもすぐにできるし無意味な安心感があります
"週末は家でクローリングしているよ" と言えば何だかモテそうだし
しかし、残念ながらこの方法ではモテません
なぜなら、この方法がモテないのは全て手作業でやる必要があるからです
クロールしたい対象が数千ページもある場合はとても太刀打ちできません
何の戦略もなくがむしゃらにテンションを上げているうようなものです
これじゃあモテません
クローリング 2.0 時代
さて、クローリングという言葉だけで簡単にモテるわけではないという現実を理解したところで、
何とかしてこの作業を自動化したらモテるのではないか?と考えました
そこで wget と grep と sed を使い HTML のテキストを切り貼りして情報を抜き出す方法を考えました
"bashスクリプトでクローリングを自動化しているから今週末は空いているよ" と言えば何だかモテそうだし
モテるクローリングを自動化したしこれで最強にモテるぜ!bash 最高!ヒーハー!と思って満足してました
しかし、そんな夢心地もつかの間
残念ながらこの方法でも永久にモテることはありません
まず、この方法では HTML をただのテキストファイルとして解析する必要があります
ひたすら正規表現と自分との戦いです
クロール対象のページやサイトが変わると HTML から文字を抽出する正規表現を1から考え直す必要があります
HTML の構造を完全に無視しているので、せっかくきれいな構造でつくられているサイトでもさほど労力は変わりません
そして、wget やプログラムの関数で HTTP リクエストを送り受け取った素のレスポンスには javascript 実行前の素の HTML しか含まれていません
なので、AngularJS、BackboneJS などのフレームワークや Ajax などにより javascript で HTML を描画しているサイトの場合、その実行後の HTML を見ることができないのです
つまり、レスポンスとして受け取った直後の HTML と描画された後の HTML は異なっている場合があるということです
※いわゆる SEO 対策でも同じことが問題になるわけですね
なので、ページにアクセスしても手に入った html はただの空の body タグだけ、というような悪夢のような展開に陥るわけです
自分がよく知っているターゲットには強くても、知らない新しいターゲットには人見知り
更に、今日の俺はイケているぞ!という勘違いをしたまま突進していき、フタを開けてみたら何も実りがない
気づいた頃には時すでに遅し、というようなものです
これじゃあモテません
クローリング 3.0 時代 ← いまここ!
これまでの方法では全くもってモテないという現実を突き付けられました
- もう一生モテないんじゃないか?
- そもそもクローリングでモテようとしていること自体が間違いなんじゃないか?
- スタバで MacBook Air を開いてソイラテを飲んでいる方がモテるんじゃないか?
という疑念が湧いてきます
ですがきっと、世界中のモテないクローラー達も同じようにモテるための方法を求めているはずです
Google でさえモテるために世界中の頭脳を駆使して日々模索し続けているはずです
そんな葛藤の中、とうとう僕は考えつきました
クローリング 2.0 時代の利便性を残しつつ、もっと簡単に柔軟に情報を抜き出すことができればきっとモテるだろう
ターゲットが誰であろうと汎用的に対応できれば必ずやモテるだろうと
真実を見極める目を持つことが重要だと
そう、今こそクローリングでモテる時代だと
どうです、モテそうでしょう?
2. モテるのはどんな方法なのか
イマドキのモテるクローラー達はどんな方法でサイトをクロールしてモテているんだろうと一生懸命ググりました
必死でググりました
モテているやつらにはきっと共通するものがあるはずです
数ある情報の中からモテる可能性が高そうなこんな方法を見つけ出しました
そしてこれらを実現するための素晴らしいツールに出会いました
それが今回ご紹介する PhantomJS と cheerio です
これらを使いこなすことで、ついに僕らはモテるクローリング 3.0 の時代へ突入することができます
どうです、モテそうでしょう?
3. PhantomJS & cheerio の最強タッグ
PhantomJS、cheerio を使用して Web サイトクローリングを実施します
これらのツールがどんなものかを簡単に説明します
PhantomJS
PhantomJS - Scriptable Headless Browser
めっちゃ簡単にいうと CLI で操作する web ブラウザです
PhantomJS is a headless WebKit scriptable with a JavaScript API.
と公式サイトに書かれている通り、画面がないブラウザで操作は全て javascript で行います
PhantomJS は通常の Web ブラウザと同じレンダリングエンジンを備えているので、ページ内の javascript が実行された後の HTML を取得することができます
また、アクセスした Web サイトを通常の web ブラウザと同じように操作することができ、画面キャプチャを画像や PDF で保存する機能もついています
今回はクローリングのために利用していますが、Web アプリケーションのe2eテストにも利用されているようです
PhantomJS を使えば Web サイトに対してのあらゆる操作を高度に自動化するのに使えますね
どうです、モテそうでしょう?
cheerio
めっちゃ簡単にいうと node.js 上で使える jQuery です
jQuery 本家のライブラリではなくて、node.js 用に jQuery を再実装したモジュールらしいです
これを利用することで、node.js から jQuery と同じように DOM 操作ができます
HTMLの文字列を解析するため、ファイルに保存された HTML に対して処理できるのがこれの利点です
わざわざそんなことしなくても、PhantomJS 内で jQuery を読み込んでも同じことができるんじゃない?と思ったそこのあなた
今回僕がやりたかったことでは、HTML の取得と HTML の解析は別々にした方が使い勝手がいいと判断したので cheerio を使うことにしました
どうです、モテそうでしょう?
4. クローラーの実装方法
それでは具体的に PhantomJS & cheerio の使い方を見て行きましょう
サンプルコードを github に置きました
github.com
サンプルコードにある方法はこんな流れです
- PhantomJS でレンダリング済みの HTML を取得してファイルに保存
- cheerio で HTML ファイルをパースして情報を抽出
ちょっとややこしいんですが js ファイルの違いはこんな感じです
- crawler.js
- phantomjs を操作する javascript コード
- analysis.js
- node.js 上で実行する javascript コード
それぞれのコードは以下のようにコマンドラインから実行します
$ phantomjs crawler.js http://www.google.com path/to/file.html $ node analysis.js path/to/file.html
URL のリストを作っておけば、こんな感じにして自動でクロールできます
for f in `cat urlList.txt` do phantomjs crawler.js $f path/to/$f node analysis.js path/to/$f >> siteData.tsv done
このサンプルでは analysis.js でWeb サイトのタイトルと description を tsv 形式で標準出力するようにしていますが、実装次第でどうにでも拡張できます
取得後の HTML や取得した情報を mongodb や elasticsearch に入れるとイケてるクローラーが作れそうな気がしてきますね
どうです、モテそうでしょう?
5. PhantomJS の よくある質問
そもそもどういうことかよく分からないんだけど
"ヘッドレスな web ブラウザ" という以上に簡潔でいい説明はありません
web ブラウザ上の javascript コンソールの中にコードを書く感じで操作できます
Firefox とか Chorome とは全然違うんでしょ?
PhantomJS は QtWebKit という webkit をベースとしたレンダリングエンジンを利用しています
メジャーなブラウザだと WebKit2 を使っている Safari が一番近いようですが、厳密には違うものなので Firefox や Chorome と同じようにブラウザ毎の
微妙な違いはあります
Selenium とは何が違うの?
Selenium はブラウザの操作を自動化するためのツールなので Firefox、Chrome、IE などのブラウザを操作するための API を提供してくれるものですが、PhantomJS は Web ブラウザそのものです
とはいえ、どちらも e2e テストなどによく利用されているものではあるので、ブラウザ操作の自動化という点ではどちらも似たような感じですが
Firefox、Chrome、IE などのブラウザでテストをする必要がある場合は Selenium を使うということになると思います
PhantomJS を node.js 上から使うことはできないの?
これは確かにその通りなんですよね
僕も PhantomJS を見つけた時は
- node.js のモジュールで PhantomJS があればもっとモテそうなのに
- なぜもっとモテようとしないんだ
と思いました
実際のところ node.js から PhantomJS を呼び出すためのモジュールはあります
GitHub - amir20/phantomjs-node: PhantomJS integration module for NodeJS
処理をイベントドリブンで書かないといけないので正直サクッと使えるかどうかというと微妙です
モテたい気持ちが全面に出すぎたせいでコールバック地獄に苦しんでいるようでは結局モテないので、今回は PhantomJS をそのまま使いました
また、同期処理で書ける node-phantomjs-sync というモジュールもあります
GitHub - sebv/node-phantomjs-sync: sync version of phantomjs-node
これはこれで使えそうでしたが、今回はわざわざ node.js と連携させる理由がなかったので使いませんでした
とはいえ、本格的なクローラーを作る場合や、あるシステムの一部として PhantomJS を使おうとするとこれらのモジュールが必要になってくるはずです
その先には更にモテる未来が待っていることでしょう
PhantomJS と node.js の javascript コードを同じにはできないの?
実際にコードを書いてみると、それぞれの javascript のコードはほとんど同じに見えるので、きっとこの疑問がでてくるはずです
ですが、ここには地味に難しい問題があるので、PhantomJS と node.js は全く別の実行コンテキスト上にある、と考えなくてはいけません
PhantomJS は PhantomJS 内部に自分の javascript エンジンを持っています
Webkit に含まれる JavaScriptCore というエンジンで、HTML ページ上の javascript を実行しているようです
また、PhantomJS 自身を操作する時の javascript もこの JavaScriptCore を使っています
なんで PhantomJS は node.js のモジュールではないの?という質問がQ&Aにありました
PhantomJS - Frequently Asked Questions (FAQ)
The short answer: "No one can serve two masters."
と仰っているように、
node.js の実行環境 (Google V8 JavaScript Engine) と Webkit の実行環境 (JavaScriptCore) は javascript ではあるけど全く違うものなので、これらをくっ付けるというのは想像よりもとんでもなく難しい問題なわけです
つまり、Web ページ上の javascript は JavaScriptCore 上で実行し、PhantomJS の操作は V8 で実行する、
となるとたしかにわけわからん感じになりそうですよね
Google Chrome の javascript エンジンは V8 なので、もしかしたらそういう製品を作れる可能性はあります
ただ、仮に両方が同じエンジンを使っていたとしても、それぞれの実行コンテキストを同じにしちゃっていいのか?というと、それは簡単な話では無さそうです
とにかく現状では、これはそれだけのパワーをかけてまで PhantomJS がやりたいことではないはずなので、こういった状況になっているわけですね
ちなみに、先に紹介した phantomjs-node などの node.js モジュールを使う場合には、このあたりを理解できてないとハマるかもしれません
どうです、モテそうでしょう?
6. クローリングは慎重に!
Web サイトのクロールをする場合は対象のサイトがクロールを明示的に禁止している場合があります
※例えば Twitter は事前承諾なしのスクレイピングは禁止!と利用規約に書かれています
禁止していなかったとしても過度にサイトにアクセスすると状況によっては DoS 攻撃と同じ事になってしまいます
負荷が掛かりすぎないように同時アクセス数を減らしたり、リクエストの間隔を空けるなどして Webサイトに迷惑がかからないようにしましょう
過去にはクローリングが原因でサイトがダウンしてしまい、偽計業務妨害と判断されて逮捕されたなんて事例があるらしいです・・・
モテたいがために Web サイトに迷惑をかけるようではいつまで経ってもモテません
やろうとするクローリングによって Web サイトに迷惑を掛けないか、自分は本当にモテているのか、お茶でも飲んで落ち着いてから考えましょう
7. まとめ
さて、ここまでモテる Web サイトクローリングのやり方について紹介してきました
もしかすると皆さんもうお気づきかもしれません
この際ハッキリ言いましょう
結局のところ、Web クローリングをすればモテるというわけではありません
Web クローリング自体はモテるためにあるものではないのです
もしもあなたが Web クローリングだけでモテようと思っているとしたら?
あなたは大きな間違いを犯していると言えるでしょう
あなたがクローリングをしようとしたとき、その先には本来パワーを掛けるべき本当にモテるための作業があるはずです
クローリング をしてモテることが最終目的ではないのです
モテたいから Web サイトクローリングをする
などという愚かな選択はして欲しくないのです
○○でモテるためには Web サイトクローリングが必要
だから私は PhantomJS と cheerio を使って楽にクローリングして、モテるための○○に100%のパワーを注ぐ
という賢者の選択をできるようになって欲しいのです
ぜひともクローリングを有効活用してモテるための本来のタスクに100%のパワーを注ぎましょう
今回は PhantomJS と cheerio を使った、確実にモテる Web サイトクローリング & スクレイピングのやり方についてご紹介しました
どうです、モテそうでしょう?