GASとPhantomJsCloudで動的なWebページをスクレイピング(Javascriptページに対応)
通常のGoogle Apps Script(GAS)のスクレイピングでは、Javascriptによる動的なWebページはスクレイピングできません。
しかし、PhantomJsCloudのAPIを利用すれば、動的なページをスクレイピング可能です。
そこで、GASとPhantomJsCloudを組み合わせたスクレイピング方法を解説します。
Google Apps Scriptはスクレイピングに便利
Google Apps Script(GAS)はスクレイピングにとても適したプログラミングサービスです。
サーバーレス環境でスケジュール登録による定期的なスクレイピングが可能です。
GASは無料で利用できるため、費用0でスクレイピング環境を構築できます。
Javascriptの動的ページはGASによるスクレイピングが難しい
ただ、Google Apps Script(GAS)ではJavascriptで動的に生成されるWebページのスクレイピングが難しいです。
URLにアクセスしてHTMLソースを取得した際に、Javascriptの動的ページだとソース上には取得したいデータの記述がないためです。
例えば、Yahooのトップページの場合、Chromeブラウザでソースコードを表示しても、HTMLソース上では、ブラウザで表示されている文字列が含まれていません。
ヤフーのページはJavaScriptで記述されていて、動的に生成されているからです。
そのため、GASのデフォルトの機能やスクレイピング用のライブラリを利用しても、動的なページから情報を取得することができません。
PhantomJsCloudのAPIで動的ページのレンダリングが可能に
Javascriptで表現されクライアントPCで動的に生成されるWebページに対し、Google Apps Script(GAS)でスクレイピングする方法はないのでしょうか?
実は、動的なWebページをGASでスクレイピングする方法は、あるサービスを組み合わせることで実現可能です。
それは、PhantomJsCloudというサービスを組み合わせることです。
PhantomJsCloudは、ヘッドレスブラウザのクラウドサービスで、Javascriptを実行してレンダリングされたHTMLデータを取得可能です。
- PhantomJsCloudで動的なページをレンダリング
- GASでレンダリング結果をスクレイピング
上記の手順でPhantomJsCloudのAPIとGASを組み合わせることによって、動的なページのスクレイピングができるようになります。
PhantomJsCloudで動的ページをスクレイピングするGASサンプルコード
実際にPhantomJsCloudのAPIを利用して、Javascriptの動的WebページをGoogle Apps Scriptでスクレイピングする方法をサンプルコードで解説します。
1.PhantomJsCloudのAPIを利用するために、利用登録とAPIの取得します。
※PhantomJsCloudのAPI発行手順は以下の記事を参照ください。
2.APIキーを発行したら、GASのスクリプトエディタを開き、以下の記事に従って、APIキーをスクリプトプロパティに設定します。
Key:PHANTOMJSCLOUD_ID、Value:(発行したPhantomJsCloudのAPIキー)
3.スクリプトエディタでPhantomJsCloudを利用するサンプルコードを記述します。
function phantomJSCloudScraping(URL) {
//スクリプトプロパティからPhantomJsCloudのAPIキーを取得する
let key = PropertiesService.getScriptProperties().getProperty('PHANTOMJSCLOUD_ID');
//HTTPSレスポンスに設定するペイロードのオプション項目を設定する
let option =
{
url: URL,
renderType: "HTML",
outputAsJson: true
};
//オプション項目をJSONにしてペイロードとして定義し、エンコードする
let payload = JSON.stringify(option);
payload = encodeURIComponent(payload);
//PhantomJsCloudのAPIリクエストを行うためのURLを設定
let apiUrl = "https://phantomjscloud.com/api/browser/v2/" + key + "/?request=" + payload;
//設定したAPIリクエスト用URLにフェッチして、情報を取得する。
let response = UrlFetchApp.fetch(apiUrl);
//取得したjsonデータを配列データとして格納
let json = JSON.parse(response.getContentText());
//APIから取得したデータからJSから生成されたソースコードを取得
let source = json["content"]["data"];
return source;
}
このサンプルコードのphantomJSCloudScraping関数は、PhantomJsCloudから動的なWebページのレンダリングされたHTMLソースを取得します。
自作関数でphantomJSCloudScrapingを利用することによって、動的なWebページのスクレイピングが可能になります。
Yahooトップページをスクレイピングするサンプル
先程紹介したPhantomJsCloudのAPIを利用する自作関数を利用して、動的なWebページをスクレイピングしてみます。
今回、Javascriptで動的に生成されるページ例として、Yahooトップページ(https://yahoo.co.jp)をスクレイピングし、ヤフトピの記事タイトルを取得します。
※ヤフートップのソースを見ると、HTMLの情報がないことが分かります。
Google Apps Scriptでヤフートップページのスクレイピングをするサンプルコードを紹介します。
function getYahooTopics() {
//スクレイピングしたいWebページのURLを変数で定義する
let url = "https://www.yahoo.co.jp/";
//PhantomJsCloud用の独自関数で動的なWebページのHTMLデータを取得する
let html = phantomJSCloudScraping(url);
//Parserライブラリを使用して条件を満たしたHTML要素を抽出する
let newsList = Parser.data(html)
.from("<h1 class="\"_3cl937Zpn1ce8mDKd5kp7u\"" > ")
.to("")
.iterate();
//ログ出力でスクレイピング結果を表示する
console.log(newsList);
}
実行ログの出力結果で、ヤフトピのニュースが8本スクレイピングできていることが確認できます。
このようにPhantomJsCloudにスクレイピングしたいURLをAPIリクエストすることで、動的なWebページでもGASによるスクレイピングが可能です。
まとめ・終わりに
今回、Google Apps Script(GAS)で動的なWebページをスクレイピングする方法を紹介しました。
GASはスクレイピングに便利なプログラミング言語ですが、ヤフートップのようなJavascriptで動的に生成されるWebページの場合にはスクレイピングが難しいです。
ただ、PhantomJsCloudというサービスを利用し、APIで動的なページのHTMLコードを取得することで、GASによるスクレイピングが可能になります。
最近はJavascriptで構成され、動的にレンダリングされるWebページが増えています。
もし、スクレイピングしたいページが動的なWebサイトの場合、今回紹介したヤフートップのスクレイピング方法を参考に、スクレイピングしてみてください。
ディスカッション
コメント一覧
ヤマタケさん、とても参考になる記事を書いていただき、ありがとうございます。
「スクリプトエディタでPhantomJsCloudを利用するサンプルコードを記述」したところ、以下のエラーが発生してしまいます。
どのような対策が必要か教えていただけたら嬉しいです。
エラー
Exception: Request failed for https://phantomjscloud.com returned code 400. Truncated server response: {
“originalRequest”: {
“pages”: [
{
“renderType”: “HTML”,
“outputAsJson”: true
}
]
},
“content”: {
“url”: null,
“name”: “e… (use muteHttpExceptions option to examine full response)
phantomJSCloudScraping @ PHANTOMJSCLOUD_ID.gs:17
>ギンコ様
コメントありがとうございます。
いただいたエラーが表示されたとのことですが、取得したいページのURLは何になりますでしょうか?
エラー内容だけだとわかりかねるのですが、urlの応答値がnullになっているため、URL周りにエラー原因がありそうです。
お手数をおかけしますが、サンプルコードのようにYahooページが取得できるか確認いただき、そちら問題なければ、取得しているURLが正常かご確認いただけますでしょうか。
よろしくお願いします。