CasperJSでスクレイピングやログインからの投稿などを行うための方法と注意点
2018-08-29 2018-09-03
PhantomJSを元々使っていたものの、waitがかけにくいとか、微妙によくわからない動作をすることがあったりと、不満点が色々あったので、CasperJSに乗り換えました。乗り換えたと言っても、CasperJSで利用するヘッドレスブラウザにPhantomJSを選択したので、実際には「PhantomJSを拡張するCasperJSを利用することにした」と言った感じです。
今回は、いくつかのサイトに対するスクレイピング(HTML情報の取得)と、特定サイトにログインしてからの操作(例えば、CMSにログインして記事を投稿するなど)を試してみましたが、CasperJSの知識というよりも、Javascriptの制約とか、サイト毎に異なる仕様の部分で引っかかることが多かった印象です。
ということで、色々試した結果得られた「とりあえず動かす方法」と「いくつかの注意点」をお伝えしていきます。
CasperJS、PhantomJSのインストール
CasperJSの公式サイトを見ると、「npmで簡単インストール!」な雰囲気になっていますが、今回私が受けた要件は「CentOSのroot権限が使えないサーバでやってくれ」ということだったので(sudoも使えない)、npmは使えません。
仕方ないので、CasperJSの公式サイトから直接ファイルをダウンロード。適当な場所に置いて、.bash_profile(.bashrc)でbinをPATHに追加。
同じく、PhantomJSもダウンロードページからファイルをダウンロード。適当な場所に置いて、.bash_profile(.bashrc)でbinをPATHに追加。
これで準備完了。もちろん、出来るのであれば、/usr/binに追加したり、/usr/binからシンボリックリンク貼って、/lib/node_modulesに追加したりしても構いません。
1 |
casperjs --version |
を叩いて、バージョンが返ってくれば問題なし。PhantomJSのPATHが指定されていないと「No such file or directory; did you install phantomjs?」エラーが返ってきますが、この手順でPATH指定エラーが返ってくるのであれば、PATHが正しく設定されていないということなので、PhantomJSもCasperJSと同じく、PATHを設定してあげてください。
CasperJS実行ファイルの作成
とりあえず、適当なサイトにアクセスして5秒待ってからキャプチャー取るだけのプログラム。
書き方は色々ありますが、初心者でもわかりやすいんじゃないかと思われる書き方にしてます。かっこよく書きたい人はそれぞれ好きに変えてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var casper = require("casper").create({ // 表示サイズを一応設定 viewportSize: { width: 1920, height: 1080, }, // debug情報表示 verbose: true, logLevel: "debug" }); var url = "適当なurl"; casper.start(); casper.open(url); // 前のステップが完了したらthen内の処理が実行される casper.then(function() { casper.wait(5000); this.capture("capture.png"); }); casper.run(); |
sample.jsというファイル名で作ったので、これをCasperJSインストール済のサーバに配置。
1 |
casperjs sample.js |
で実行。実行すると、capture.pngが生成される。
CasperJSでスクレイピング
サンプルと大差ありませんが、evaluateを使う必要が出てきます。
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 |
var casper = require("casper").create({ // 表示サイズを一応設定 viewportSize: { width: 1920, height: 1080, }, // debug情報表示 verbose: true, logLevel: "debug" }); // Yahooでお試し var url = "https://www.yahoo.co.jp/"; // YahooはuserAgentセットしないと弾かれる var agent = "適当なuserAgent"; casper.userAgent(agent); casper.start(); casper.open(url); casper.then(function() { casper.wait(5000); // 読み込んだページ内のデータを取得、変更する場合はevaluateを使う var news = this.evaluate(function() { // 新着ニュースの1件目のテキストを取得 return document.querySelector("#topicsfb > div.topicsindex > ul.emphasis > li:nth-child(1) > a").textContent; }); // consoleに出力 require("utils").dump(news); }); casper.run(); |
1 |
casperjs scraping.js |
Yahooトップページのニュース1件目を取ってみました。
「”数合わせ横行 官僚の法令無視写真”」
なるほど…。写真アイコンの文字まで取って来てしまった模様。
とりあえずお試しで出力してみましたが、本気でスクレイピングをするのであればファイルに保存などすれば良いでしょう。
ファイルの保存方法はCasperJSと全然関係ないので書きませんが、「require(‘fs’)」とかで調べればすぐわかります。
CasperJSでログイン
ここからが本番です。何らかのサイトにログインして、その後、設定を変更したり、記事を投稿したりするための処理を考えてみます。
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 |
var casper = require("casper").create({ // 表示サイズを一応設定 viewportSize: { width: 1920, height: 1080, }, // debug情報表示 verbose: true, logLevel: "debug" }); // 何らかのログイン画面 var url = "適当なログイン画面のurl"; // ログイン画面はuserAgentセットしないと弾かれがち var agent = "適当なuserAgent"; casper.userAgent(agent); casper.start(); casper.open(url); // ログイン casper.then(function() { casper.wait(5000); // id,pass入れてsubmitする時にはfillを使う(第二引数の連想配列のキーはname属性を指定する) this.fill('form', {id: 'login_id', password: 'login_password'}, true); }); // ログイン後 casper.then(function() { casper.wait(5000); // ログイン後の処理を色々 this.click('何らかのセレクタ a'); // 適当なaタグクリックするとか }); casper.run(); |
1 |
casperjs login.js --cookies-file=cookies.txt |
適当なサイトにログインするための簡単な処理だけ書いてます。ログイン後は適当なaタグをクリックしてますが、セレクタの指定はchromeの機能使うと楽で確実になります。
「右クリック→検証→Elementsの中のタグを右クリック→Copy→CopySelectorで、対象タグのセレクタをクリップボードにコピー」
実行する際、ログインする場合はcookie情報が必要なケースがあるので、適当なファイルにcookieを記載して利用します。
ログインした後は色々やりたい放題ですが、サイトによってはbot回避のための様々な仕掛けが施されているので、上手く動かないことも多々あります。
以下、色々な仕掛けの例。
reCAPTCHAがログイン画面にある
画像選んだり、汚い文字を頑張って入力したりするやつ。
機械学習とか使わない限り、基本的にお手上げです。
submit出来ない
submitボタンが無く、buttonを叩くとjsで処理されるような仕組みになっているやつ。
fillを使わず、this.click使うと回避出来たりする。出来なかったりもする。
モーダルが出まくって邪魔される
ログイン後、色々な個所でモーダルが出てきて邪魔されるやつ。
this.captureで丁寧に1処理づつキャプチャー取って、どこで邪魔されてるかを把握してthis.clickとかでモーダルを閉じれば回避できる。
たまに、ブラウザで普通にアクセスした時には出ないモーダルが出る場合があるが、スクレイピングでセレクタ情報を取得出来れば何とかなる。
aタグがtarget=”_blank”だらけ
対象タグの属性を変えてしまうか、casper.openを使ってページを直接開くようにする。
ランダムでパラメーター付加されるような仕組みだった場合は、前者しか使えない。
編集しようと思ったら、入力欄が外部ドメインのiframeで編集できない
これは無理。javascriptの限界。
色々ありますが、こういったことに出くわす場合は「CasperJSとか使ってbot処理するんじゃねえよ」と言われているに等しい状況なので、基本的には辞めておきましょう。何らかの規約に触れるケースもあるので、アカウントの削除くらいは当たり前、場合によっては業務妨害で訴えられる可能性もあります。