スクレイピングの手法
rubyでのスクレイピング
本ブログではruby + selenium webdriverをメインで扱っていますが、
この技術を使ってよくスクレイピングしています。
私はrubyでのスクレイピングではseleniumかgemのnokogiriを使っています。
ruby + selenium webdriver(windows)のセットアップ方法は以下の記事で紹介しています。
windowsならruby + selenium webdriverも環境設定は15分で終わる | katsulog
nokogiriでのスクレイピングではブラウザなどが立ち上がることなく、コマンドライン上のみで完結します。
google spread sheet(google apps script)でのスクレイピング
googleのspreadsheetでエクセルでいうマクロのような機能を使ってスクレイピングを行うこともできます。
そのマクロをgoogle apps script(GAS)というのですが、主にJavaScriptで実装していきます。これを使うと取得した結果をspreadsheet上に表示することができます。
また、spreadsheet上の値を取得してGASに組み込むこともできます。
GASでのスクレイピングは定期実行などの処理がGUIで簡単に設定できます。
単純にWEBページ上のソースを取得するだけであればとても簡単で、GoogleDrive上の処理なので無料で行うことができ、環境設定も要りません。
さらにGoogleApps各種の機能とも連携できるので、gmailを送信するなんてことも可能です。
このブログは入門的なことにはあまり触れないので、GASに関してこれから始めたいという方はgoogleで検索してみてください。
たくさん記事がありますし、とても簡単です。エクセルのマクロに触れたことがあればプログラミング未経験者でも容易に使用できるでしょう。
JavaScriptの入門や練習にも良いでしょう。
GASではログインが必要なサイトのスクレイピングはできない?
GASはコードはWEBブラウザ上の専用エディタに書くのですが、実行自体はブラウザが立ち上がることなく、サーバー上で処理されて返ってきます。
そのためログインする必要があるサイトでは、ログインした先にある情報は取得できないのではないかと思われている方もいるようです。
しかし、POSTでログイン情報を投げて、GETでcookie情報を取得することによって、ログインした先のページも取得することができます。
GASでのログイン機能の実装
では、もしもアフィリエイト というログインが必要なサイトでのGASを実装してみましょう。
コードを実際に試したい方は もしもアフィリエイト に登録してください(ええ、アフィリエイトです)。
まずはPOSTの実装です。
// POSTデータ
var payload = {
"account" : "あなたのユーザーID",
"password" : "あなたのパスワード",
}
// POSTオプション
var options = {
"method" : "POST",
"payload" : payload,
"followRedirects" : false
}
次にPOSTを投げるURLを指定します。
もしもアフィリエイトでのログイン画面のURLは
https://secure.moshimo.com/af/shop/login
ですが、このURLにPOSTデータを投げてもログインはできません。
実際にPOSTを投げているURLを調べるにはChromeやFirefoxの拡張である HTTP Headers を使うと良いでしょう。
HTTP Heagersを起動させてもしもアフィリエイトにログインするとログイン後の画面で以下のように表示されます。

一番上に
POST https://secure.moshimo.com/af/shop/login/execute
と表示されていますね。
これがPOSTを投げるURLになります。
では、POSTリクエストを書いてみましょう。
// アクセス先(http headerなどでPOSTのURLなどを調べる) var url = "https://secure.moshimo.com/af/shop/login/execute" // POSTリクエスト var response = UrlFetchApp.fetch(url, options);
GASのクラスとメソッドである”UrlFetchApp.fetch” の第二引数に先程設定した optionsが ありますね。
これでログイン可能になります。
次にPOSTリクエストから返ってきたヘッダー情報からcookieを取り出して、GETメソッドをoptionsに設定しましょう。
// レスポンスヘッダーからcookieを取得
var cookies = response.getHeaders()["Set-Cookie"];
// ログインで認証されたcookieはヘッダーで使用
var headers = { 'Cookie' : cookies };
options = {
method : "get",
headers : headers,
followRedirects: true, //リダイレクトあり
};
これでログイン状態を維持する準備ができましたね。
では、ログイン後のトップページのURLにアクセスしてページのソースを取って来てみます。
トップページのURLは
http://shop.af.moshimo.com/af/shop/index
ですね。
var topUrl = "http://shop.af.moshimo.com/af/shop/index"
response = UrlFetchApp.fetch(topUrl, options);
var content = response.getContentText("UTF-8");
これで content の中にトップページのソースが格納されました。
実際にcontentの中身を見るには Logger.log(content) などとしてから実行すれば、ctrl + Enterでログが表示されます。
まとめ
では、せっかくですからログイン後のソースからユーザー名を取り出してみましょう。
ページのソースをブラウザから見るとユーザー名部分は
<p class="name-box">大浦 勝也
となっているので、ここを正規表現で取り出してみます。
全体のコードはこうなります。
function myFunction() {
// POSTデータ
var payload = {
"account" : "あなたのユーザーID",
"password" : "あなたのパスワード",
}
// POSTオプション
var options = {
"method" : "POST",
"payload" : payload,
"followRedirects" : false
}
// アクセス先
var url = "https://secure.moshimo.com/af/shop/login/execute"
// POSTリクエスト
var response = UrlFetchApp.fetch(url, options);
// レスポンスヘッダーからcookieを取得
var cookies = response.getHeaders()["Set-Cookie"];
// ログインで認証されたcookieはヘッダーで使用
var headers = { 'Cookie' : cookies };
options = {
method : "get",
headers : headers,
followRedirects: true, //リダイレクトあり
};
var topUrl = "http://shop.af.moshimo.com/af/shop/index"
response = UrlFetchApp.fetch(topUrl, options);
var content = response.getContentText("UTF-8");
// ユーザー名をuserNameに格納
var myRegexp = /<p\sclass="name-box">(.+?) /
userName = content.match(myRegexp);
Logger.log(userName)
}
実行した後にctrl + Enterでログを見ると

と表示されましたね。
以上になります。
GASを使うと日々の情報を取得し、整形してspreadsheetに表示したり、gmailで受け取ることなどができてとても便利です。
ルーチン化されている日々の業務はGASで簡略化できますね。
というわけでGASの実装も承っております。
お仕事の依頼はtwitterからDMで話掛けていただければと思います。


コメント
このページはとても勉強になりました。ありがとうございます。質問なのですが、現在もしもアフィリエイのHTTP HeagersのPOSTの部分はGETになっていますが、他の私がPOSTURLを必要としているサイトでもGETしか出てきません。その場合はどうしたらいいでしょうか。ご教授ください。そのせいか、ログインの画面から、中に入れず、困っています。他のヘッダーチェッカーを使ってみたのですが、、、
返信遅れてしまってすみません。
postのデータもあるはずなのでhttp live headerの中をよく見てみてください。
指定された属性の値が無効です: Header:null(行 31、ファイル「コード」)
となり 実行出来ません
その場合はどうしたらいいでしょうか。ご教授ください。
記述した内容を書いてみてください~!
おそらく同じ症状になったので返信します。
サイトのコードをコピペするとエラーが出てきました。そこでresponse.getResponseCode();でresponsecodeを見てみると301でした。調べてみると永久的な移転を意味するcodeらしいです。
解決策として
var url = “https://af.moshimo.com/af/shop/login/execute”
に書き換えるとと正常な動作になりました。
質問させてください。
こちらのページを参考に実行してみたのですが
contentにはログイン前のページのデータが入ってしまいます。
ログインに失敗しているように見受けられるのですが
CSRF対策されているページの場合はこちらのコードだと
ログインに失敗してしまいますでしょうか?
ちなみに
4~5行目のID/Pass
15行目のアクセス先
30行目のtopUrl
のみ変更しています。
HTTP Headersでログインのための本当のURIが得られるので見てみてください。
初学者です
この方法でtwitterにログインして値を取得することは可能ですか?
hiddenされたデータも渡してみたのですが、、
HTTP Headersは使っていませんが、/sessionsにpostしています