【VBScript(WSH)】エラーの回避方法『オブジェクトがありません』

【VBScript(WSH)】エラーの回避方法『オブジェクトがありません』
VBSでスクレイピング組んでれば必ず遭遇するであろうエラー『オブジェクトがありません』
コード:800A01A8
ソース:Microsoft VBScript 実行時エラー
いやいや、存在するかしないかで場合分けしたいんだって!
存在してればレコードはあるから取得して、存在してなかったらスキップしたいのよ。
と思っていても意図した動きになったりならなかったり。
と言う事で、ここら辺まとめてみます。
意図した動きをさせるためのチェックポイント
動的サイト内に下のようなHTMLがあったとします。
1 2 3 4 5 6 7 8 9 |
#レコードがある時 <div class="listbase"> <div class="hogelist"> <ol> <li>○○○</li> <li>▲▲▲</li> </ol> </div> </div> |
さて、検索したらレコード件数がゼロ。その時、動的サイトは大別すると下の3パターンになっていると思います。
■タイプ1:一部のタグ(olとかtableなど)を残して値が消えている
1 2 3 4 5 |
<div class="listbase"> <div class="hogelist"> <ol></ol> </div> </div> |
■タイプ2:レコード情報が(olとかtableなどの)タグごと消えている
1 2 3 4 |
<div class="listbase"> <div class="hogelist"> </div> </div> |
■タイプ3:無いよと言う値が挿入されている
1 2 3 |
<div class="listbase"> <div class="searchNonItems">データは存在しません</div> </div> |
スクレイピングの際はこの中のどのパターンかを把握しておきます。
タイプに合わない形で分岐を書いていると「オブジェクトが無い」と怒られます。
どうすればいいか答え的なもの
考え方は2つです。
- 検索レコードのオブジェクトを存在確認して分岐する
- エラーオブジェクトの存在確認をして分岐する
そしてやってはいけない事(エラーの元凶)は次の2つです。
- 検索レコードにテキストがあるかを存在確認して分岐する
- エラーオブジェクトのテキストがあるか確認して分岐する
オブジェクトそのものの存在確認をする場合は【有無】で分岐できますが、オブジェクト内の値で分岐しようとした場合は『オブジェクトの存在が大前提』となります。
なので[ objIE.Document.getElementsByTagName(“li”).innerText ]などと書いた場合、タイプ1-3全てで liタグは存在しないのにテキストを取ろうとしている=「オブジェクトがありません」とエラーが出てきてしまいます。
オブジェクトが無いってどういう事?
例として【タイプ1:一部のタグ(olとかtableなど)を残して値が消えている】で見ていきます。
正しく動くIF分岐script
1 2 3 4 5 6 7 8 9 10 |
Dim inText If IsObject(objIE.Document.getElementsByClassName("hogelist")(0).getElementsByTagName("li")) Then 'オブジェクトが存在しない時の動作 MsgBox("データは見つかりません") Else 'オブジェクトが存在する時の動作 inText = objIE.Document.getElementByClassName("hogelist")(0).getElementsByTagName("li")(0).innerText MsgBox("inText") End If |
こんなのはNGです。
1 2 3 4 5 6 7 8 9 10 |
Dim inText If IsEmpty(objIE.Document.getElementsByClassName("hogelist")(0).getElementsByTagName("li")) Then 'オブジェクトが存在しない時の動作 MsgBox("データは見つかりません") Else 'オブジェクトが存在する時の動作 inText = objIE.Document.getElementByClassName("hogelist")(0).getElementsByTagName("li")(0).innerText MsgBox("inText") End If |
1 2 3 4 5 6 7 8 9 10 |
Dim inText If IsNull(objIE.Document.getElementsByClassName("hogelist")(0).getElementsByTagName("li").innerText) Then 'オブジェクトが存在しない時の動作 MsgBox("データは見つかりません") Else 'オブジェクトが存在する時の動作 inText = objIE.Document.getElementByClassName("hogelist")(0).getElementsByTagName("li")(0).innerText MsgBox("inText") End If |
タイプ1の場合、<li>も<li>に囲まれたテキストも存在しません。
その為、EmptyやNULLで存在確認をしようとすると、そもそものliタグが存在していない為「オブジェクトが無い」と怒られる事になります。
存在確認の鍵は【 IsObject / IsEmpty / IsNull 】を使いこなすこと
私もしばらく戸惑っていましたが、VBScriptでスクレイピングを書こうとした場合、この3つの違いを理解している事は大切です。
- IsObject(変数):変数がobjectか否かを確認。変数が存在しない場合はオブジェクトではないと回答
- IsEmpty(変数):変数に値が入っているかを確認(入っていない場合がTRUE)。NULLの場合、NULLという値が入っているのでFALSEが返る。TRUEとなるのはEmptyで初期化されている場合のみ。変数が存在しない場合はobjectNothingのエラーが出る。
- IsNull(変数):変数にNULLが入っているかを確認(NULLの場合がTRUE)。初期化した値(変数=Empty)の場合FALSEが返る。変数が存在しない場合はobjectNothingのエラーが出る。
具体的に見てみましょう。
IsObjectの動作
こんなスクリプトを実行してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Option Explicit Dim objTEST '変数にNULLを代入 objTEST = NULL IF IsObject(objTEST) Then MsgBox("TRUE") Else MsgBox("FALSE") End If '変数をSETしNothingで初期化 Set objTEST = Nothing IF IsObject(objTEST) Then MsgBox("真") Else MsgBox("偽") End If '変数をEmptyで初期化 objTEST = Empty IF IsObject(objTEST) Then MsgBox("正") Else MsgBox("否") End If |
メッセージボックスで出てくる値は【FALSE / 真 / 否】です。NothingでもオブジェクトとしてセットされていればTRUEを返します。
IsEmptyの動作
IsObjectと同じくこんなスクリプトを実行してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Option Explicit Dim objTEST '変数にNULLを代入 objTEST = NULL IF IsEmpty(objTEST) Then MsgBox("TRUE") Else MsgBox("FALSE") End If '変数をSETしNothingで初期化 Set objTEST = Nothing IF IsEmpty(objTEST) Then MsgBox("真") Else MsgBox("偽") End If '変数をEmptyで初期化 objTEST = Empty IF IsEmpty(objTEST) Then MsgBox("正") Else MsgBox("否") End If |
この答は【FALSE / 偽 / 正】です。ちなみに、オブジェクトをEmptyで初期化する事は出来ません。[ Set objTEST = Empty ]と書くと「オブジェクトがありません」と怒られます。
IsNullの場合
同じ方法でこんなスクリプトを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Option Explicit Dim objTEST '変数にNULLを代入 objTEST = NULL IF IsNull(objTEST) Then MsgBox("TRUE") Else MsgBox("FALSE") End If '変数をSETしNothingで初期化 Set objTEST = Nothing IF IsNull(objTEST) Then MsgBox("真") Else MsgBox("偽") End If '変数をEmptyで初期化 objTEST = Empty IF IsNull(objTEST) Then MsgBox("正") Else MsgBox("否") End If |
この答は【TRUE/ 偽 / 否】です。[ Set objTEST = NULL]と書いた場合もEmpty と同じく「オブジェクトがありません」と怒られます。
まとめ
ここまでを表にするとこんな感じ。
変数 = NULL | 変数 = Empty | 変数 = “” | Set 変数 = Nothing | 備考 | |
---|---|---|---|---|---|
IsNull() | TRUE | FALSE | FALSE | FALSE | 変数がobjectの時は無条件でFALSE。 空文字 ”” もNULLでは無いためFALSE。 スクレイピングではまず使い道はない。 |
IsEmpty() | FALSE | TRUE | FALSE | FALSE | 初期化されているかを判別する。 つまりは、Flag的使い方が可能。 何かの処理で値が入ればそれを軸に分岐を組める。 |
IsObject() | FALSE | FALSE | FALSE | TRUE | オブジェクトか否かを判断する。 スクレイピングでは存在確認で使いどころが多い。 変数に値が入っていてもオブジェクトでなければFALSE。 |
ClassNameで抽出した値が存在しているかを確認するのはIsObjyect一択。
-
前の記事
【VBScript(WSH)】このスクリプトには、悪質なコンテンツが含まれている為、ウィルス対策ソフトウェアによりブロックされています。 2020.10.28
-
次の記事
WEBスクレイピングがBANされる3つの理由 2020.11.04
コメントを残す