Excel (VBA)

Excel VBAに関するフォーラムです。
  • 掲示板への投稿には会員登録(無料)が必要です。会員登録がまだの方はこちら
  • 掲示板ご利用上のお願い」に反するご記入はご遠慮ください。
  • Q&A掲示板の使い方はこちらをご覧ください
トピックに返信
質問

 
(指定なし : 指定なし)
Webスクレイピングによる画像取得について
投稿日時: 21/11/11 15:01:45
投稿者: TATSUYA.ich

お世話になっております。
 
とあるサイトの画像を一定のタグカテゴリ毎に複数種類取得し、フォルダに格納するコードを書いておりますが、うまく画像を取り込めません。
 
恐らく、画像のデータ表示中にデータを取得してしまうため、ダウンロード中のデータを取得してしまうと思うのですが、何か解決策はございませんでしょうか。
 
会社のセキュリティの関係から、一部のコードのみですが助言を頂けると嬉しいです。
 
dim Np as integer
dim URL as string
dim SaveDir as string
dim Filename as string
dim Result as Long
 
 
 For Np = 0 to objIE.document.getElementsByClassName("〇〇")
   URL = objIE.document.getElementsByClassName("〇〇")(Np).getElementsByTagName("img")(0).src
       
      FileName = objIE.document.getElementsByClassName("〇〇")(Np).innerText & ".jpg"
       
      SaveDir = Thisworkbook.Path & "\photo\" & FileName
      Result = URLDownloadToFile(0,URL,SaveDir,0,0)
 
      URL = objIE.document.getElementsByClassName("××")(Np).getElementsByTagName("img")(0).src
   
   SaveDir = Thisworkbook.Path & "\〇〇〇\" & FileName
      Result = URLDownloadToFile(0,URL,SaveDir,0,0)
 
Next Np
 
以上、よろしくお願いいたします。

回答
投稿日時: 21/11/11 15:41:13
投稿者: Suzu

対策としては
 
IEによるWebスクレいピングについて
https://www.moug.net/faq/viewtopic.php?t=81029
 
と、同じです。
 
読み込み完了まで処理を待機すれば良いと思いますよ。
 
 

引用:
一度、時間差を作るようなコードを追加してみます!!

はどの様にされたのですか?
 
 
InternetExplorerオブジェクト なのであれば
・Busyプロパティ
・readyState プロパティー
の値により、DoEvents をループさせるのが常套手段です。
 
https://www.vba-ie.net/ 辺りが参考になるのではないでしょうか。
 
 
 
ただ。。
2022/6/16 に MSの IEへのサポートが終了する予定です。
併せて、各 WEBサイトも、IEのサポートを順次 終了していくと思われます。
 
今後も継続的に使用してゆくなら、
対象サイトの IEへのサポートについてアナウンス がないか確認しておいた方が良いでしょう。
 
他の手法/オブジェクト を使用するにしても
InternetExplorerオブジェクトの 手法が 応用できる部分もあるでしょう。

投稿日時: 21/11/11 16:51:22
投稿者: TATSUYA.ich

Suzu様
 
お世話になっております。
 
いつもありがとうございます。
 
時間差を設けるために、Resultで一度画像取得した後に、Sleep1000で1秒程度時間をを設けたり、Busyプロパティ、readyState プロパティーで以下のコードを挟み込んでみたりしてみても同様のエラーとなってしまいます。
 
Result = URLDownloadToFile(0,URL,SaveDir,0,0)
 
ここの部分でデータを取得しているかと思われますが、この処理が完了するまでに待たせるにはどのようなコードが適切なのでしょうか。
 
2枚目以降の画像がうまく取得できないです(ダウンロード中の画像になってしまいます)。
 
因みに、IEがサポート終了になるのはわかっているのですが、会社の体質が古く、セレニウムなどのダウンロードが許可されていません。
 
もし、将来的にIEでのスクレイピングが難しい状況になった場合は、自宅PCで分析をしようと考えております。
 
何度もすみません。
 
よろしくお願いいたします。

回答
投稿日時: 21/11/11 17:53:17
投稿者: simple

横から失礼します。
 
URLDownloadToFile は同期処理なので、ファイル保存が終了するまで処理待ちになりますね。
 
For Np = 0 to objIE.document.getElementsByClassName("〇〇")
がおかしくないですか?
objIE.document.getElementsByClassName("〇〇")はオブジェクトの配列なので、
.Countがあればそれを使うし、なければUboundなんかで個数をとれませんか?

回答
投稿日時: 21/11/11 21:35:16
投稿者: simple

For Np = 0 to objIE.document.getElementsByClassName("〇〇").length -1
でしたね。
 
補足:
同期処理というのは、その処理が終わるまでは、次の行には進まない、という意味です。

回答
投稿日時: 21/11/12 16:44:03
投稿者: Suzu

引用:
時間差を設けるために、Resultで一度画像取得した後に、Sleep1000で1秒程度時間をを設けたり、Busyプロパティ、readyState プロパティーで以下のコードを挟み込んでみたりしてみても同様のエラーとなってしまいます。
  
Result = URLDownloadToFile(0,URL,SaveDir,0,0)
  
ここの部分でデータを取得しているかと思われますが、この処理が完了するまでに待たせるにはどのようなコードが適切なのでしょうか。

 
読み込みが完了していない状態でドキュメントを取得してしまうため
url等も不完全になってしまっているのかな。と思ったのですが。。
 
Simple さんの
引用:
For Np = 0 to objIE.document.getElementsByClassName("〇〇").length -1
でしたね。
が本線でしょうね。
 
読み込みの問題なのであれば、シングルステップで進めた際には問題が出ないでしょうから
 
1. シングルステップにて確認。
2. 同時に、ローカルウィンド/イミディエイトウィンド等で 各変数の値が
  意図している 値と合っているか 確認してみてください。
 
3. その上で、
  別プロシージャにて、
   Result = URLDownloadToFile(0,URL,SaveDir,0,0)
  の各変数に、ローカルウィンド等で確認した値を入れて動作確認
 
の順でしょうかね。

トピックに返信