質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

1回答

2652閲覧

VBAスクレイピングが理解出来ません。

LBciel.

総合スコア18

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2020/01/26 13:33

編集2020/01/27 06:00

やりたい事

**【URL】【画像】【商品名】【発売日】【値段】**を抜き出してExcel2016に入力する。
下記対象サイト

HTML

12 ▾<div id="Main"> 3 ▾<a href="URL1" class"s d a"> 4  ▾<div class="img"> 5 <img src="https://...jpg?" Srcset="https://...jpg? x1, https://...jpg? x2"> 6 </div> 7  ▾<div class="one"> 8 ▾<div class="two"> 9 <span class="title">商品名</span> 10 </div> 11 <div class="three">発売日</div> 12 ▶<div class=""></div> 13 ▾<div class="four"> 14 ▾<div class="five"> 15 ▾<span style="color: #888888;"> 16 <strike>¥1,520</strike> 17 </span> 18 <br> 19 "¥1,140 " 20 </div> 21 </div> 22 </div> 23 <div style="clear: left;"></div> 24 </a> 25 ▶<a href="URL2" class"s d a">…</a> 26 ▶<a href="URL3" class"s d a">…</a> 27 ▶<a href="URL4" class"s d a">…</a> 28 </div> 29

※必要でないような部分は記述していません。classはそのまま表示するわけにもいきませんので英数字を入れています。出来ない部分は無理に出力も必要ありません。
<a href>内のclassは一部商品を除き同一でした。)
もし上記だけでは情報不足という事であれば、その前後も追記致します。

<a>タグの中に欲しい情報が全て収まっており、ブラウザ上は横並びで一行になっています。
<a>タグ1つが1行で、その下URL2,3,4…と下に続いています。その全てをページを変えて抽出が目標となっております。

丸投げになっている事は重々理解しています。しかしこの部分だけ丸一日様々なサイトを閲覧し、試してみたもののまったく成果が無く、やむなくこちらのサイトを利用した次第です。

Linksでページ上全てのURLを抜き出す事は出来たのですが、必要な部分がその1/3程で全く使いこなせませんでした。

出来ている部分

InputBox → ワード入力 → IE起動 → ログインページ → ID・pass入力 → 検索エンジンのあるURLに移動 → 検索エンジンにワード入力 → 検索ページに移動 + 次のページをクリック

Excel

1Sub Wait(ByVal objIE As InternetExplorer) 2' Dim Lc As Integer 3 Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE 4 DoEvents 5 Loop 6 7' IE表示待ち(たまに抜けない場合もあるので1万回ループで強制抜け) 8' Lc = 0 9' Do While objIE.Busy = True Or objIE.readyState <> 4 Or Lc > 10000 10' DoEvents 11' Lc = Lc + 1 12' Loop 13 14End Sub 15 16Sub ログイン() '「ツール」「参照設定」「Microsoft HTML Object Library」「Microsoft Internet Controls」忘れずに 17 18 Dim keyword As String 19 keyword = InputBox("検索したいワードを入力してください。") 20 21 Dim objIE As InternetExplorer '操作するIEを入れる「箱」つまりオブジェクト変数を準備 22 Set objIE = New InternetExplorer '箱に新しいIEをセット 23 24 objIE.Visible = True 'IEを画面に表示する 25 objIE.navigate "https://s.com/login/home/?goto=" '管理画面ページのURLを指定 26 Wait objIE 27 28 Dim htmlDoc As HTMLDocument 'HTMLDocumentというHTMLドキュメントを表すオブジェクト 29 Set htmlDoc = objIE.document 'InternetExplorerオブジェクトのDocumentプロパティ 30 31 With htmlDoc 32 .getElementById("AccountName").Value = "ЖЖЖ" 'ユーザー名を指定 33 .getElementById("Password").Value = "ЖЖЖ" 'パスワードを指定 34 .getElementById("Login").Click 35 End With 36 Wait objIE 37 38 objIE.navigate "https://s.com/search/" '検索エンジンのあるページへのURLを指定 39 Wait objIE 40 41 With htmlDoc 42 .getElementById("store_nav_search").Value = keyword 43 .getElementById("store_search_link").Click 44 End With 45 Wait objIE 46 47' Dim page As Long 48' For page = 1 To 5 49' Wait objIE 50' Set htmlDoc = objIE.document 51 52 Dim anchor As HTMLAnchorElement 53 With htmlDoc 54 .getElementById("search_resultsRows").Links 55 Debug.Print anchor.href 56 End With 57 58' With htmlDoc 59' .getElementsByClassName("pagebtn")(0).Click 60' End With 61' Wait objIE 62 63' Next page 64 65End Sub

※サイトを参考に「これで動いた」程度の理解状況です。使用したものを完璧に理解しているわけでは御座いません。
コメント部分の半端なプログラムは、後々使うであろうものを残しています。
anchor部分は現状試しているもののエラーで動かない部分です。

出来れば切に希望する教えて頂きたい事

スクレイピングの抽出の流れは外堀から考えていく事だと思うのですが、その方法が全く理解出来ていません。
こちらを作成後、今度はPythonでスクレイピングを行う予定ですので、考え方を理解したいと考えております。(IEでの操作で対象サイトのドロップダウンするものをクリックしても反映されない等あり、Pythonでの習得も考えております。)

【getElement】【getElements】等、単体かコレクションかでスタートからやり方が違っていると思うのですが、各々の進め方を理解できるように教えて頂ければ幸いです。

単体とコレクションがあるという事だけしか理解出来ていません。使い方がサイトのHTMLの条件次第ということもHTMLを使用したことがあるため理解しています。これ使えそう!と思ってもそれを使うための技術が無く、根本的にそこからでは出来ないのか出来るのかがわからないのも悩みの種になっています。

又、ログインが必要なサイトでログインが必要な事は理解できます。ログインするプログラムを作る際、ログインをしているかどうかの確認が必須だと考えております。調べてみたところcookieを利用する等の情報はあるものの詳細が御座いません。下手にログインも含めたプログラムは組まないほうが良いのでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2020/01/26 13:40

「出来ている部分」のコードも掲載できないのでしょうか? 何をどこまで理解されているか不明では回答がつきにくいかと思います。
LBciel.

2020/01/26 14:03

更新しました。ご確認ください。
yuuskeccho

2020/01/26 14:04

タグに”VBA”を指定しているようですが、VBAは関係ないですよね? Pythonで実装するのであれば"Python”を指定して下さい。
LBciel.

2020/01/26 14:05

こちらはVBA上で行っています。
meg_

2020/01/26 14:12

現状、商品名等を取得したいサイトへは画面遷移できているのですよね?
LBciel.

2020/01/26 14:15

出来ています。そのサイトのデベロッパー内HTMLが上部になります。 そこから【URL】【画像】【商品名】【発売日】【値段】を抜き出す「やり方」が理解出来ておりません。
meg_

2020/01/26 14:19

実際のサイトが見られないので出来るか不明ですが、クラス名"s d a"でタグを取得して(複数あるなら全部)、そこからその子要素のタグを辿っていって必要な情報だけを取得するって感じでしょうか。
LBciel.

2020/01/26 14:29 編集

※一部説明が間違っていたため修正しました。 <a>タグの中に欲しい情報が全て収まっており、ブラウザ上は横並びで一行になっています。 <a>タグ1つが1行で、その下URL2,3,4…と下に続いています。その全てをページを変えて抽出が目標となっております。 一先ず初めのページ内の【URL】【画像】【商品名】【発売日】【値段】を抜き出す事をご教示頂きたいと考えております。
LBciel.

2020/01/26 14:55 編集

話を遮ってしまい申し訳ございません。 本当にやり方がわからず、<div id="Main">内にすべての<a href>が入っているため、id指定を行いその中の…と考えておりましたが、idの場合.getElementById()で単体になるので全ての中身が抜き出せないと勝手に考えてしまっております。おそらく現状の理解度では何もできそうもありませんので、meg_様の方法を試したいと考えております。 ※日をまたぎそうな時間ですので、お手すきの時間にご教示願えれば幸いです。
meg_

2020/01/26 15:23

id属性があれば良いのですがなかったりあっても何故か複数のタグに使用されている場合もあります。 質問の例ですと「getElementsByClassName("s d a")」が良いでしょう。
LBciel.

2020/01/27 01:05

有難う御座います。そちらに絞って組み方を調べながら試していきます。
guest

回答1

0

ベストアンサー

呈示のHTMLの場合で回答します。(VBAコードとは乖離がありますので。)

HTMLの構造は、id="Main" のdiv要素の中に、複数のa要素(class="s d a")が含まれている。
a要素の中に商品名(class="title")、発売日(class="three")、値段(class="five")が含まれている。

複数のa要素を取得するには、
htmlDoc.getElementById("Main").Links(これはダメでした)
htmlDoc.getElementById("Main").getElementsByTagName("a")

htmlDoc.getElementsByClassName("s")
のどちらかでいいでしょう。

どちらにしても複数の要素になりますので、すべての要素に対してFor Eachループで処理するようにします。
下記ですべてのa要素(sクラス)のURLが取得できます。

html

1 Dim anchor As HTMLAnchorElement 2 For Each anchor htmlDoc.getElementsByClassName("s") 3 Debug.Print anchor.href 'URL出力 4 End With

また、a要素の中に、商品名等が含まれていますが、calss属性が設定されていますので、
getElementsByClassNameで取得しますが、これはコレクションを返します。
コレクションの最初の要素を取得するには、getElementsByClassName("title")(0) というようにします。
ということで、下記で【URL】【画像】【商品名】【発売日】【値段】が取得できます。

html

1 Dim anchor As HTMLAnchorElement 2 For Each anchor htmlDoc.getElementById("Main").Links 3 Debug.Print anchor.href 'URL 4 Debug.Print anchor.getElementsByClassName("title")(0).innerText '商品名 5 Debug.Print anchor.getElementsByClassName("three")(0).innerText '発売日 6 Debug.Print anchor.getElementsByClassName("five")(0).innerText '値段 7 End With

投稿2020/01/26 17:54

編集2020/01/27 04:39
hatena19

総合スコア33715

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LBciel.

2020/01/27 01:48 編集

ご回答有難う御座います。一先ず上の方法で試してみたところ… Dim anchor As HTMLAnchorElement For Each anchor In htmlDoc.[("search_resultsRows")].Links Debug.Print anchor.href 'URL出力 Wait objIE Next anchor 上記で試してみましたが、Forの部分で実行エラー438:オブジェクトは、このプロパティまたはメソッドをさぽーとしていません。となりました。For分は【In】【Next anchor】【Wait objIE】を追加し、[]で囲った部分はそれで囲わないとダメと出てきましたので囲い、実行は出来たのですがエラーとなりました。 End Withで〆られていたので、上部(ログイン位置)で各々区切っていたWith htmlDocのEnd Withを最下部まで引き延ばしました。
hatena19

2020/01/27 01:19

すみません。コードに間違いがあったので回答を修正しましたので、もういちど回答をみてコードを修正してください。 具体的には .getElementById が不足していました。
LBciel.

2020/01/27 01:45

With htmlDoc ログイン部分 ... ... Dim anchor As HTMLAnchorElement For Each anchor In htmlDoc.getElementById("Main").Links Debug.Print anchor.href 'URL出力 Wait objIE Next anchor End With 上記のやり方で試してみたところ、エラー91:オブジェクト変数またはWithブロック変数が設定されていません。とエラーが出力されました。Withの部分は各々区切って設定した方が良いのでしょうか?
hatena19

2020/01/27 02:03 編集

下記のコードで試してみてください。 Set htmlDoc = objIE.document Dim anchor As HTMLAnchorElement For Each anchor In htmlDoc.getElementById("Main").Links Debug.Print anchor.href 'URL出力 Next anchor "Main" の部分は実際のID名にしてください。 Withに関しては、 htmlDoc.getElementById・・・ というように htmlDoc. から書き始めれば、Withで囲む必要はないです。 With で囲めば省略できますが、繰り返し使わなければ読みづらくなるだけです。メリットを考えて使うようにすればいいでしょう。
LBciel.

2020/01/27 02:33 編集

大変失礼しました。2回目Mainのままでした…変更後も同じ内容でした。 End With Set htmlDoc = objIE.document Dim anchor As HTMLAnchorElement For Each anchor In htmlDoc.getElementById("search_resultsRows").Links Debug.Print anchor.href 'URL出力 Next anchor 上記で試してみましたが、「Forの部分で実行エラー438:オブジェクトは、このプロパティまたはメソッドをさぽーとしていません。」となりました。 このコードを打ち込んだ場所は、上部[出来ている部分]のコメントに挟まれたanchorの部分を上書きして実行しております。 For Each文はgetElementsのコレクション限定だと思っておりましたが、Linksを使用すると動作するものなのでしょうか。
hatena19

2020/01/27 02:51

Links もコレクションを返しますので、動作するはずです。 下記ではどうなりますか。 Set htmlDoc = objIE.document Dim anchor As HTMLAnchorElement For Each anchor In htmlDoc.Links Debug.Print anchor.href 'URL出力 Next anchor あと、下記も試してみてください。 Set htmlDoc = objIE.document Dim anchor As HTMLAnchorElement For Each anchor In htmlDoc.getElementsByClassName("s") Debug.Print anchor.href 'URL出力 Next anchor "s"の部分は実際のクラス名で。
LBciel.

2020/01/27 03:38 編集

Set htmlDoc = objIE.document Dim anchor As HTMLAnchorElement For Each anchor In htmlDoc.Links Debug.Print anchor.href 'URL出力 Next anchor 1つ目のコードは、エラー70:書き込みできません。とエラーが出るものの、イミディエイトにURLやjavascript等の情報が出力されました。数が多すぎて数え切れませんが・・・ どこで止まったかF8で確認したところ、出力終了後?また一番上に戻っていました。おそらくログイン済み状態でまたログインで引っかかったのではないでしょうか。その際はまた別のエラー表示が出ましたが・・・ Set htmlDoc = objIE.document Dim anchor As HTMLAnchorElement For Each anchor In htmlDoc.getElementsByClassName("search_result_row ds_collapse_flag app_impression_tracked") Debug.Print anchor.href 'URL出力 Next anchor 2つ目のコードは、何もエラーが出ないものの、何も出力されませんでした。 F8で確認したところ、For Each文の次「Debug.Print anchor.href」をスルーしてEnd Subに移動していました。 試しに回答2つ目の商品名等の部分も入力してみたものの、For文の次はEnd Subに飛んでしまいます。
hatena19

2020/01/27 04:33

空白で区切られたクラス名は、どれか一つだけ指定してください。 For Each anchor In htmlDoc.getElementsByClassName("search_result_row")
LBciel.

2020/01/27 06:19 編集

返信有難う御座います。 空白の部分、その様な条件もあるのですね。 【URL】【商品名】【発売日】【値段】の抽出が出来ました! 下記がその際のコードとなります。 Set htmlDoc = objIE.document Dim anchor As HTMLAnchorElement For Each anchor In htmlDoc.getElementsByClassName("search_result_row") Debug.Print anchor.href 'URL Debug.Print anchor.getElementsByClassName("search_capsule")(0).innerHTML '画像 ' Debug.Print anchor.htmlDoc.images(0).src '画像拡張子のみ取得? Debug.Print anchor.getElementsByClassName("title")(0).innerText '商品名 Debug.Print anchor.getElementsByClassName("search_released")(0).innerText '発売日 Debug.Print anchor.getElementsByClassName("search_price")(0).innerText '値段 Next anchor …しかし、F5での実行であるとイミディエイトに反映されず、F8での実行で反映されました。【Wait objIE】をどこかで入れる必要があるのかと思い試してはいるのですが改善が見られません。どういった原因が考えられますでしょうか? 画像の取得に関しまして、1つ目は<img src="">内全てを取得する内容で成功しました。内部に3つデータがあり、1つだけというのはやはり無理なのでしょうか。 2つ目のもので試したところ【anchor】を抜けばコードが通り、拡張子が画像の物だけ取得しているようでした。(0)としたのが原因か、1つのものだけ繰り返して取得していました。
LBciel.

2020/01/27 12:40

F5実行でエラーと画像はまだHTML取得で止まっておりますが… ページ切り替えの問題を乗り越え、セルへの出力も叶いました! 最後までお付き合い頂いて本当に有難う御座いました! 最低限やりたい事の条件は満たせましたので、hatena19様の回答をベストアンサーとし、一旦区切らせて頂きます。 もしお時間があるようであれば、残りのエラーや改善できる部分にお付き合い頂けましたら幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問