VBScript(WSH):JavaScriptのカレンダー操作してスクレイピングする方法
VBScript(WSH):JavaScriptのカレンダー操作してスクレイピングする方法
VBScriptはIEの力を借りて何のインストールも無しにDOM操作できる事が最大のメリットです。
が、jQueryの猛威に対処するには中々面倒です。
inputタグで記載されている内容を変えてもダメな時がある
例えば楽天市場の【売上データ (時間別)】のページなんかがコレです。

こんな感じで入力フォームをクリックするとカレンダーが表示されます。
日付を選択すると日付が変わるし、手打ち入力も出来ると言う便利なUIなのですが、スクレイピングでは難点が。
HTML内に複数の日付記載箇所がある
上記楽天売上データ分析のカレンダー箇所を取り出してみます。
<table border="0" cellpadding="6" cellspacing="0">
<tbody>
<tr bgcolor="#eeeeee">
<td>
<input type="hidden" name="app" value="sales_data_hourly">
<font size="-1">表示日:</font>
<script>
document.write('<input id="date_disp" type="text" name="date_disp" value="2020/12/29">');
document.write('<input id="date" type="hidden" name="date" value="20201229">');
</script>
<input id="date_disp" type="text" name="date_disp" value="2020/12/29" class="hasDatepicker">
<input id="date" type="hidden" name="date" value="20201229">
<noscript>
<input id="date" type="text" name="date" value="2020/12/29">
</noscript>
<input type="submit" value=" 表示 " onclick="wait_msg.style.display='block';">
</td>
</tr>
</tbody>
</table>
(中略)
<script type="text/javascript">
var APP = {};
if (typeof jQuery !== 'undefined') {
APP = {
currentDate: "2020年12月29日",
elm: {form: $("#form_date"),
date: $("#date"),
picker: $("#date_disp"),
chart: $("#chart_container"),
loader: $("#chart_loader"),}
}
(中略)
APP.datepicker = APP.elm.picker.datepicker({
defaultDate: "20201229",
minDate: "2019/01/01",
maxDate: "2020/12/29"
});
(中略)
jquery_check(0);
</script>
日付の記載箇所がこんなに沢山あります。ちなみに、この楽天さんのカレンダーの場合は12行目の日付が本命です。
<input id="date" type="hidden" name="date" value="20201215">
ここを変えて表示をクリックしてあげると抽出変更が出来ます。※上の場合は2020/12/15の抽出が出来る。
楽天市場はまだわかりやすいですし、JavaScriptメインのScriptではないので操作もしやすいです。
が、Yahooの一部やAmazonなんかではHTMLの解析だけでカレンダーを操作する事は中々に困難です。
inputをDOM操作で変えても動かない時がある
上の例だとUI上に表示されている日付は14行目になります。
<input id="date" type="text" name="date" value="2020/12/29">
なので、DOM操作でここを変更して表示クリックをしてしまいそうですが、前項で記載した通り本命は12行目。
14行目を変更しても抽出データを変える事が出来ません。
楽天市場のスクレイピングは楽です。
目につく形(<input type=hidden ...>)で変更すべき箇所を残していてくれてますから。
AmazonなんかではAjaxで組んでおり『DOM操作で日付を変えたのにデータが変わらない』事が間々あります。
これはinputに記載した日付をAjaxが送るべきところに送っているからなのですが、DOMでは動かない様なのです。
こんな時に行うのは【人的操作の模倣】
人的操作の模倣 = objShell.SendKeys( "{TAB}" ) などのキーボード操作です。
ブラウザをキーボードで操作してinputにカーソルを合わせそこに入力すれば、JavaScriptも動いてくれます。
Set objShell = WScript.CreateObject ("WScript.Shell")
days = "2020/12/15"
'カーソル移動
objShell.SendKeys({TAB 20})
'日付を記載
objShell.SendKeys(days)
この方法ならAmazonのようなカレンダーも突破する事が出来ます。
と言う事で、依頼を受けたVBScriptではTABでカーソル移動させていたのですがデッカイ問題が発生しました。
その為、TABボタンでカーソル移動したのに目的地を通り越したりたどり着かなかったりと...。
これでは安定したスクレイピングはできません。
ページ構成が変わる場合は【フォーカス】して実行しよう
フォーカスはDOM操作の1つで『目的地にカーソルを移動してくれる』という便利な機能です。
これを使えばTABボタンを押す回数なんて気にしなくても【人的操作の模倣】が可能になります。
今回の例のようなPOSTしている値が見えてる簡単なSCRIPTではDOM操作で完結して問題ありません。
でも、2個以上の値をPOSTして整合性を取ってるスクリプトも存在してるので「納期短縮」しようとしたら解析業務の増えるDOMよりもターゲットにフォーカスして変更すると言う手段を採用した方がいいかもしれません。
まとめ
いやまぁね、最初からフォーカス使えばよかったんだけどさ。
色んなサイトのページ解析してると「なんで同じIDが同一ページ内に2つ存在してるんだよ」みたいな事もありまして、変化の少ないページだとTABの方が楽で安定してたんですよね。
で、すっかり頭から抜け落ちていたと。
思い出したおかげで何とか安定型として納期に間に合わせることできて一安心。
でも、こんな初歩を忘れているとは...大反省です。


