VBScript(WSH)で作ったYahoo!ストアクリエイターPROのデータ収集で不具合修正
VBScript(WSH)で作ったYahoo!ストアクリエイターPROのデータ収集で不具合修正
今までうまく動いていたスクリプトで突然エラーが発生しました。
「お問合せ」リンクからご連絡ください。
自動操縦scriptの結果なので「お問合せ」する事も出来ず、約8時間Yahoo!の動作解析してました。
何が変わっていたか
動いていたスクリプトなので、Yahoo側かPC側の何かが変わったことは間違いありません。
で、確認したところ今までIEで動いていた(であろう)2箇所の動作がエラーを招いてました。
- クリックアクションで動くJavaScriptによるClassとStyleの変更
- [ Y-m-d ]に整形した日付データをValueに記載した時、なぜか [May-6 ~~~] と言う表記で登録される
クリックアクションで動くJavaScriptによるClassとStyleの変更
具体的には『ストアクリエイターPROの統計データで出力データの変更を行うカレンダー』の箇所です。
クリックアクションでカレンダーも表示されていたはずでしたが、真っ白。
カレンダーが出てきません。
このカレンダーのつらいのは、TABでの位置調整(日付選択)が出来ずキーボード操作による選択が不可能な所です。
そのくせカレンダーの位置(例えば表示している月とか)を変更すると次の読込でも変更が生きているという仕様。
なので、すべてをDOM操作で実装するしかなくて、取得したい日付をクリックアクションで操作すると言った荒業も少々厳しい。
「まぁDOM使えれば色々できるからいいか」という事で解析スタート。
Windows×IEはそこら辺が(インストール不要の)基本仕様で出来るから便利ですよね。
具体的な調整箇所
'カレンダーの表示'
objIE.Document.getElementsByClassName("daily input")(0).Click
これでJSが変更していた2か所が動かなくなっていました。なので、強引にDOMで変えてしまいます。
'BOXを開く'
objIE.Document.getElementById("widgetCalendar").style.height = "235px"
'カレンダーを表示に変更'
objIE.Document.getElementsByClassName("datepicker")(0).style.position= "absolute"
'カレンダーに選択状態を作る'
Dim dy
dy = objIE.Document.getElementsByClassName("datepickerDays")(1).getElementsByTagName("td")(10).innerText
objIE.Document.getElementsByClassName("datepickerDays")(1).getElementsByTagName("td")(10).outerHTML = "<td class='datepickerSelected'><a href='#'><span>"&dy&"</span></a></td>"
ここら辺がクリックアクションで自動的に変わってたパーツ。
最初は「これが変わらなくなったからエラーが出るようになった」と思ってました。
解決した後に原因究明してプログラムを小型化する作業をしていたところ、本質はココではない事が解りました。
[ Y-m-d ]に整形した日付データをValueに投げると [May-6 ~~~] と言う表記に変わる
途中この現象に気づいて修正を加えていたのですが、なぜかその時は解決しなかったんですよね。
きっと余計なことやってたんだろうなぁ。
元々(エラー発生の状況で)実際に書いていたコードはこんな感じです。
'最新の日付を取得'
strFormattedDate = SItemStaDate(objIE,2)
'1週間前を取得'
oldDate = oldDateCalc(strFormattedDate,"W",1,NULL)
'差異を計算'
difDate = DateDiff("d",oldDate,strFormattedDate)
For dt=0 To difDate-1
dDt = DateAdd("d",dt,oldDate)
'カレンダー表示'
objIE.Document.getElementsByClassName("daily input")(0).Click
'日付変更'
objIE.Document.getElementsByName("datefrom")(0).value = objDate
objIE.Document.getElementsByName("dateto")(0).value = objDate
'適応'
objIE.Document.getElementsByClassName("apply")(0).Click
'ダウンロード処理'
objIE.Document.getElementsByClassName("btnDownload")(0).Click
Next
'------------------------------'
'最新データの日付を取得する(テキストで記載されている日付から取得)'
'------------------------------'
Function SItemStaDate(objIE,dty)
Dim dateMonth
Dim startDate
'期間テキストを" "で分割3つ目を取り出してdtyで指示された配列番号を取得'
dateMonth = split(objIE.Document.getElementById("txtSubTitle").innerText," ")(dty)
startDate = Replace(dateMonth,"年","/")
startDate = Replace(startDate,"月","/")
startDate = Replace(startDate,"日","")
SItemStaDate = startDate
Set dateMonth = Nothing
Set startDate = Nothing
End Function
この14-15行目が抽出する日付の指示になっています。
datefrom が期間の最初。dateto が期間の終了。
1日分だけのデータが欲しい時は同じ日を記載するとその日だけ取得できます。
※上の例だと両方に[ oldDate ]を入れているので『1日取得』になります。
本質的な問題はココに入った値が何故か[ May-6 ~~00:00:00 ] となっていた事。
上のFunctionコードでもわかる通り(最新のデータを取得したいので)最新情報の日付が記載している場所を取り出して日付文字列に加工して上に渡しています。
これで日付計算をした所で「時間が算出されるはずがない」と思っていたんですけど何故でしょう。
MsgBoxで調べてみる
MsgBoxで出力される値が[ May-6 ~~] となっていたら、ここまでの日付算出がおかしくなっていると解ります。
でも出力すると[ 2020/10/14 ]と欲しい姿でちゃんと出てきます。
う~んなんでだろう...。
日付データから強制的に文字列にする
理由は分からないけど「日付データだから問題になってるんだろう」と言う事は何となくわかります。
だって時間の設定なんて全くしてないのに置換したValueに[ 00:00:00 ]って値も入ってるんだからね。
だったら強制的に文字列に置き替えちゃえ!
と言う事で、14-15行目を次のように変更。
objIE.Document.getElementsByName("datefrom")(0).value = CStr(objDate)
objIE.Document.getElementsByName("dateto")(0).value = CStr(objDate)
はい、これで無事に元通り。
解決いたしました。
まとめ
今回のJavaScript連動箇所の動作についてはChromeでは従来通りの動きになってました。
変わった動きをしたのはIEのみ。
段々とIE包囲網が形成されてる気がする...。
やっぱ使い勝手いいからねぇ。
プラグイン化しなくても使えるDOMだもん。
その分「『変な使われ方』もたくさんされてるんだろうなぁ」と。
でもねぇ、さくらとかの固定サーバーからヘッドレスブラウザでスクレイピングするとIP-BAN食らうと何もできなくなるんだよなぁ。
やっぱスクレイピングツールはIPの変更できるAWSが最適解かなぁ。
などと色々思う所も出てくるエラー修正の出来事でした。


