
次がWEBページのソースの一部です。:
<div id = "output">
<table>
<tbody>
' <tr>
<th style = "width:120px;">項目1</th>
<td>①</td>
</tr>
<tr>
<th style = "width:120px;">項目2</th>
<td>②</td>
</tr>
<tr>
<th style = "width:120px;">項目3</th>
<td>③</td>
</tr>
この中で①②③の文字列を取得したいです。
現在は次の方法で①②③を取得していますが、別の方法で目的の要素だけ
取得したいのでご教示いただきたいです。
Temp = Driver.PageSource 'ページ全体を取得
※(高速処理の必要上上ここが不適当と判断しています)
Work = Split(Temp, "<td>") '目的情報直前の記述でSplit
A = Mid(Work(4), 1, InStr(Work(4), "<") - 1) '①
B = Mid(Work(5), 1, InStr(Work(5), "<") - 1) '②
C = Mid(Work(6), 1, InStr(Work(6), "<") - 1) '③
現在自分で調べて次のことはできています。
Cnt1 = Driver.FindElementsByTag("table").Count: Debug.Print Cnt1 '<----- 1 を表示
Cnt2 = Driver.FindElementsByTag("tbody").Count: Debug.Print Cnt2 '<----- 1 を表示
Cnt3 = Driver.FindElementsByTag("td").Count: Debug.Print Cnt3 '<----- 3 を表示
でも
Txt = Driver.FindElementsByTag("td")(1).Text '<----- Errorとなります。
よろしくお願いいたします。
A 回答 (7件)
- 最新から表示
- 回答順に表示
No.7
- 回答日時:
こんばんは、#4です
ターゲットサイトを拝見いたしました
スクレイピングで行うには難ありですね
すでに回答、アドバイスにある通りかと思います
単純に一定間隔の音源で、実行時間を調整して音源1.停止ボタン・取得・開始ボタン・音源2・停止ボタン・取得みたいに繰り返せば良いように思いますが、そのようなスクレイピングは問題ありかも知れません
楽譜となるとそれこそ時系列は重要なファクターなので最終目標を考えると確かに難ありですね。
専用のソフトなどを利用するのが、目的へは早道だと思います
(フリーのソフトで出来るのかは分かりません)
自身で作る事が目的に含まれているのなら、マイコンボードで作るのは賛成ですが、電子工作を行った事が無ければ、いろいろ揃える必要がありますので選択から外した方が良いでしょう
(私は電子工作道楽ですが・・実現する為には新たなる好奇心が必要です)
ターゲットサイトのようなアプリを要件に合わせ作成するのも良いかも知れません
(こちらの方が簡単かも・・?)
諸先輩方がNGとの回答なので他の方法を模索された方が良いと思います
全ページ取得→スプリットで目的値取得→配列に格納の流れをDo Loopで実行して80%程度が取得できているので、ピンポイントで取得する方法で対応できないかと思い挑戦しましたが残念です。
皆様のご指導ありがとうございました。
No.6
- 回答日時:
先のWebページはスクリプトで動的に生成されるものなのでご質問文のロジックでは実現困難と思います。
この目的なら Arduino とか Raspberry Pi などのマイコンボードにマイクを乗っけて、結果はExcel ワークシートにデータ出力でどうですか?
多分サンプルプログラムはあると思うので、電子工作になりますけど面白いと思います。
検索してみて下さい。
No.5
- 回答日時:
こんばんは
横から失礼しますが、後出しの対象サイトを見る限り、通常ののスクレイピングの発想では出来ないということを理解なさっていますでしょうか?
実行のタイミングもありますが、動的に生成されかつ内容が変わるものを取得したいということだと思いますけれど・・
>時系列にすべてVBAで拾って~
ご希望はわかりますが、処理のタイミングや速度の問題もあるので(=音源にもよりますけれど)、必ずしも全てをキャッチできる保証はないと思われます。
ご提示のサイトのソースを見てみるとわかりますが、初期状態ではtable要素も存在しません。
後から、スクリプトで生成されています。
ですので、実行のタイミングによっては、要素を取得できない場合も考えられます。
(そのあたりのチェックは全く行っていないようですので・・)
サイト側で表示している仕組みまでは調べていませんけれど、もしもtbody内(あるいはtable全体)をそっくり書き換えるような方法を取っているとすると、VBA側で要素を取得しても、対象が無くなってしまう可能性があります。
エラーが出る原因はその辺りにあるのではないかと思われますが・・
以下のサイトに似た様なことが記述されています。
(記述にあるのは、もっと単純な例ですけれど)
https://buralog.jp/python-selenium-stale-element …
>※(高速処理の必要上上ここが不適当と判断しています)
ページ全体を取得しなくても、table(あるいは、その親要素のdiv id="output")などの必ず存在する要素のinnerHTMLを取得すれば、確実に取得できるものと推測できます。
(ほぼ、対象部分だけに絞れるので、document全体よりも処理としては相当に軽くなるはずと思います)
一旦、取得したうえでご提示のような方法で分割すれば、エラーは出ないでしょう。
ただし、現状のように盲目的に処理をすると、対象がない場合にエラーになりますので、必ずチェックは必要と思います。
とは言え、上で述べたように連続的に取得する場合に、速度やタイミングの問題はいろいろとありそうに思われます。
仮に、速度やタイミングに問題がなくても、同じ音が連続している場合に、VBA側で複数の音と認識するのは難しいかも知れません。
このあたりの関係を十分理解したうえで処理を行わないと、まだまだ先は遠いのではと推測します。
VBAで取得するようなことをせずに、直接、スクリプトで出力時にブラウザのconsoleに併せて出力するとか、値を保持しておいて後からまとめて出力するなどのようにしてしまえば、タイミングを気にする必要もなくなるでしょうし、感知できる内容は全てミスなく取得できるものと想像します。
ただし、この方法はご提示のサイトの「利用規約」には合致しないようですので、残念ながらボツですね。
No.4
- 回答日時:
こんばんは
回答でなくすみません
スクレーピングは結局対象のソース次第だと思います
ご質問に挙げられている一部のソースでは
Txt = Driver.FindElementsByTag("td")(1).Text がエラーに成らないと
思いますし、一部なのですから当然かもしれませんがWork(4)は無いように思います
(一応検証しました)
chromedriver.exe Index of /106.0.5249.21/
Chromeバージョン: 107.0.5300.0(Official Build)dev (64 ビット)
従ってあとは想像での回答になりますね
通信に問題があり対象が重いなどの場合、または前動作で遷移などを行っている場合は、読み込みを待つようなコードを足してテストするのが良いと思います。方法はいくつかあるようで検索すると直ぐ見つかると思います
ロジックで対策される場合は、#3様のAの例をよく見かけます
読み込みを待つloopにXpathを入れれば間違えないかも・・
> 'ページ全体を取得
>※(高速処理の必要上上ここが不適当と判断しています)
取得した値をどのように使うかにもよると思いますが、
Driver.FindElementsByTag("td")(1).Textを繰り返し
複数を取得するのであれば、表の中のデータを纏めて配列に入れるなどの方法もありかもしれないと思います。例えば、
Dim ary As Variant
ary = driver.FindElementsByTag("table")(1).AsTable.Data
また、Excelへ直接書き込むなら・・不要部分を書き込むので処理が遅くなるので上記が良いかな・・
driver.FindElementsByTag("table")(1).AsTable.ToExcel Worksheets(1).Range("A1")
表になっているターゲットの値を取得した後どのように使うのかな?と
思いましたので横道にそれた回答をいたしました。
ありごとうございます。以前にも何回も救っていただいて感謝感謝です。
現在実際に試していることと、最終的に完成させたい目標を記載した方が
ご理解いただけるか思います。
最終目標は、音楽をPC内で鳴らしてその音楽の楽譜を作成することです。
今回の対象WEBページは
https://www.petitmonte.com/labo/zettai-onkan/です。
別プログラムでPC内のmp3ファイルを鳴動させると、同ページでその音楽の音階が表示されます。
今この表示を時系列にすべてVBAで拾ってシートに記録しようとしています。
Driver.PageSource でページ全体を取得して "<td>"でSplitして目的の文字列を配列変数に格納して終了後配列の内容をシートに書き込んでいます。
現在のテストはギターの1弦の各フレットの音(13個)を連続して録音したmp3を鳴動させてテストしています。ミ(E4)~ミ(E5)の13個の音階の内10個程度は拾えているのですが、いくつか拾いこぼしています。
なのでDriver.PageSourceやSplitなどで大量の文字列を処理している間に取りこぼしが発生しているのではと思い別な方法をトライしてみたいと思った次第です。ただし拾いこぼしの原因が、そうであるるかどうかはわかりません。
ひとつづつ潰してて行きたいと思っています。
よろしくお願いいたします。
No.3
- 回答日時:
こんにちは。
手がかりは DIV コンテナの ID だけですね、、Xpath を使うと良いかもです。
HTMLドキュメント内の Xpath を調べるには、Ctrl + Shift + J でブラウザの [ディベロッパーツール] を利用します。
使い方は検索して下さい。
簡易なサンプルを書きました。ソース内で
・WebElements
・WebElement
と複数形と単一形の違いに留意して下さい。
HTML内で幾つもあるであろう [td] タグを取得するので(A)では複数形(コレクション)です。(B)はそのコレクションをひとつひとつループで取り出すので単一です。
'前提 C:\temp\test.html を読み込む
'
Sub sampleProc()
Dim drv As Selenium.ChromeDriver
Set drv = New Selenium.ChromeDriver
drv.Start
drv.Get "file:///C:/temp/test.html"
'(A)
Dim elms As Selenium.WebElements
Set elms = drv.FindElementsByXPath("//*[@id='output']/table/tbody/tr/td")
'(B)
Dim elm As Selenium.WebElement
For Each elm In elms
Debug.Print elm.Text
Next
'drv.Quit
End Sub
ご指導ありがとうございます。さっそくご教示いただいたソースで試しましたがDebug.Print elm.Textで、同じエラー(実行時エラー’10’)が発生します。
No.2
- 回答日時:
No.1です。
>高速処理の必要上上ここが不適当と判断しています
推測ですけど結局ページを読み込み終了してから結果を得ないとダメだと思うので、もしかして読み込み完了する前に代入しようとしてしまいとかではないですかね?
No.1
- 回答日時:
もろ未経験者でございます。
違ってたらスルッと流してくださりませ。
https://powervbadesktop.com/web3/#toc8
ここで、
Driver.FindElementsByTag("table")(1).FindElementsByTag("td")(1).Text
とある点から推測すると直接奥にあるデータは取得できず、上からかき分けて入り込むしかないのかなと。
= Driver.FindElementsByTag("table")(1).FindElementsByTag("tbody")(1).FindElementsByTag("td")(1).Text
もしかすれば他の手段で短くできるのかもですが、未経験者なので検索してみてこれで精一杯です。
と言っても検証もできてませんけど。。。
さっそくご指導いただきありがとうございます。
ご紹介いただいたサイトは私も参考にさせていただき、同様の記述
= Driver.FindElementsByTag("table")(1).FindElementsByTag("tbody")(1).FindElementsByTag("td")(1).Text
でトライしておりましたが、
実行時エラー’10’
Stable ElementReference Error
stable element reference ; element is not attached to th page
とエラー表示されてしまいます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP htmlで複数の個数入力欄を表示させるには 1 2022/09/20 03:11
- HTML・CSS テーブルタグのセルの幅の一部だけを指定 1 2023/03/12 12:02
- JavaScript jQueryで同じクラス名のものを別物として扱いたい 1 2022/06/17 14:14
- JavaScript EasyUIのSubGrid(jquery)におけるObjectに入れた連想配列について 1 2022/05/02 11:21
- HTML・CSS 【CSS】:hasで可能? imgを含むtr要素を選択したい 1 2022/11/17 14:36
- HTML・CSS 自身のHPにYouTube動画を貼り付けるのが出来なくなり困ってます 1 2022/11/11 10:44
- AJAX JavascriptからPHPへのAjax通信でnullが返ってくる 3 2022/08/03 22:00
- MySQL SQL任意に並び替えをしたい 2 2023/08/28 10:47
- Perl PERL 1 2022/04/26 14:15
- その他(プログラミング・Web制作) python 気象データの取得 2 2023/06/20 23:54
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
チェックボックスにチェックが...
-
JavaScriptで特定のtdタグにcla...
-
プルダウンで選択すると、DBの...
-
一覧から選択した行の行番号を...
-
特定<table>内の<td>の色を変える
-
JavaScriptでテーブルをクリッ...
-
マウスをブラウザの外に出した...
-
IE以外でdisplay:noneで隠した...
-
JavaScriptでテーブルの行入れ替え
-
ラジオボタンとセルの連動
-
至急!GetElementById でtdの...
-
空のテーブルを表示させたい
-
指定した「曜日」の「時刻」に...
-
\\u30ad\\u30fc\\u30dc・・・と...
-
jQueryで行の移動
-
ブルダウン選択でページの表示...
-
【UWSC】HTML内のある部分を抽...
-
スクロールバーの表示位置を変...
-
特定の文字列を挿入
-
javascript クリックすると、あ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ハイパーリンクを別ウインドウ...
-
特定<table>内の<td>の色を変える
-
一覧から選択した行の行番号を...
-
tableの任意行にfocusをあてる
-
JavaScriptで特定のtdタグにcla...
-
プルダウンで選択すると、DBの...
-
Selenium.ChromeDriverの使い方...
-
チェックボックスにチェックが...
-
HTML中のTABLEのデータを抽出す...
-
マウスをブラウザの外に出した...
-
tdの中をクリックしたらチェッ...
-
至急!GetElementById でtdの...
-
IE以外でdisplay:noneで隠した...
-
テーブル内に表示されている数...
-
動的なtableの値を取得したい
-
テーブルの項目の値取得
-
クリックされた罫表セルの行番...
-
テーブル内に表示されている数...
-
Excelで作ったhtmlファイルのサ...
-
jqueryで表に連番No.を追加したい
おすすめ情報