必要に駆られて行った調査をまとめました。
間違いや良い代替策等ありましたらコメント下さい。
要約
- 世のウェブサイトは Valid でないことが多いので
IMPORTXML()
では値が取れないことが多い。 - 同じく
XmlService.parse()
も Valid であることが前提なのでパースエラーが起こりやすい。- 正規表現で値を取得する。
- JavaScript で動的にコンテンツを生成しているサイトでは
UrlFetchApp
でコンテンツを取得できない。- PhantomJS Cloud のようなサービスと組み合わせる必要がある。
事例
IMPORTXML()
で値が取れない。#N/A
と表示される。
IMPORTXML()
はスクレイピング対象が Valid でありことが求められる。
HTML エラーが存在するサイトでは機能しない。
IMPORTXML()
で取得した値が文字化けしている。
スクレイピングの対象が UTF-8 でないサイトである。
IMPORTXML()
は諦めてオリジナルの関数を作成し、getContentText()
で charset
を指定する。
// The code below logs the HTML code of the Google home page with the UTF-8 charset.
var response = UrlFetchApp.fetch("http://www.google.com/");
Logger.log(response.getContentText("UTF-8"));
XmlService.parse()
で値が取れない。Parse Error が発生する。
XmlService.parse()
も Valid であることが前提なのでパースエラーが起こりやすい。
XmlService.parse()
を利用せずに正規表現で値を取得する。
Code.js
function getTitle(url) {
var _options = {
method: "GET"
};
try {
var _response = UrlFetchApp.fetch(url, _options);
var _regexp = /<title>(.*?)<\/title>/;
var _title = _response.getContentText().match(_regexp);
return _title[1];
} catch (e) {
return e;
}
}
UrlFetchApp
で取得した値に目的のコンテンツが含まれていない。
UrlFetchApp
は JavaScript 実行前の HTML が返される。
JavaScript で動的にコンテンツを生成している可能性がある。
curl
等で取得できるソースを確認する。
PhantomJS Cloud のようなサービスと組み合わせる必要がある(著者は利用したことがありません)。
PhantomJsCloud を利用してスクレイピングする例:
Code.js
function getResource(target_url) {
var _options = {
url: target_url,
renderType: "html",
outputAsJson: true
};
var _payload = encodeURIComponent(JSON.stringify(_options));
var _request =
"https://phantomjscloud.com/api/browser/v2/" +
APIKEY +
"/?request=" +
_payload;
var _response = UrlFetchApp.fetch(_request).getContentText();
return _response;
}
補遺
- スクリプトに実行権限を許可するダイアログでは「詳細」をクリックする。
- Web エディタ上では JavaScript ES5 を利用する。
- しっかり書く場合は google/clasp を利用すると良さそう。