アプリ版:「スタンプのみでお礼する」機能のリリースについて

今回、QueryTableオブジェクトを使用してサイトの表をExcelのシートに取り込もうとしたのですが、Yahoo!(ファイナンス)のサイトからは表(サイトの中央の大きな表)をそのままの形で抽出できたにも関わらず、OddsPortal と云うサイトの表(これも中央の表)は取り込みができず、表の内容とは無関係な幾つかの文字列が取り込まれただけでした。
 マクロは以下の通りです(プロパティは最小限を掲載)。

Sub Table抽出比較()
  Dim strgURL As String
    'Yahoo!(ファイナンス)
    strgURL = "URL;" & "https://info.finance.yahoo.co.jp/ranking/?kd=1&m …
    'OddsPortal(サッカーのJ1リーグ)
'    strgURL = "URL;" & "https://www.oddsportal.com/soccer/japan/j1-leagu …
 With ActiveSheet.QueryTables.Add(Connection:=strgURL, _
    Destination:=ActiveSheet.Range("A1"))
   .WebFormatting = xlWebFormattingNone
   .WebSelectionType = xlAllTables
   .Refresh BackgroundQuery:=False
 End With
End Sub

 OddsPortalの表のHTML要素(目的のテーブルの前後だけ)は次のようになっています。
<div id="tournamentTable" style="display: block;">
<table class " table-main" id="tournamentTable"> ← ここが目的のテーブル
省略
</div>

 なお、念の為、以下の情報も書き添えておきます。
selector : #tournamentTable
full Xpath : /html/body/div[1]/div/div[2]/div[6]/div[1]/div/div[1]/div[2]/div[1]/div[6]/table
Xpath : //*[@id="tournamentTable"]
環境 : Windows10  Excel19(64bits)

 OddsPortalのサイトはQueryTableオブジェクトには適していないのでしょうか?
 ご存知の方、教えて頂ければ幸いです。
 宜しくお願いします。

A 回答 (2件)

>Debug.Print htmlDoc.getElementsByTagName("tournamentTable")(0).innerText


変数やオブジェクトの宣言等、細かい部分は記載がないので、上記の一行に限って言えば、
getElementsByTagNameはHTMLのタグを取得するものですから、HTMLのタグでないもの「tournamentTable」を取得しようとしても、できないと思われます。
getElementsByTagNameを使うのであれば、HTMLのタグであるものを指定する必要があります。例えば
htmlDoc.getElementsByTagName("table")(0).innnerText
※添え字の「0」が正しいかは不明

あるいは「tournamentTable」を活かすのであれば、「tournamentTable」はidですから、例えば
htmlDoc.getElementById("tournamentTable")(0).innnerText
※添え字の「0」が正しいかは不明
※getElementByIdはgetElementsByIdではないことに注意

という記述になるのではないかと思います。
    • good
    • 0
この回答へのお礼

goomaniaさん、丁寧なる回答を有り難うございました。

>getElementsByTagNameはHTMLのタグを取得するものですから、HTMLのタグでないもの「tournamentTable」を取得しようとしても、できないと思われます。
→ これについては前回の投稿でも書いたように、ダメモトで一応挿入しておいたものです。
 
>例えば
htmlDoc.getElementsByTagName("table")(0).innnerText
→ これについては "table"、" table-main" 等とし、且つ、添字を(0)、(1)、(2)と変えてはみたのですが、表とは無関係な文字列しか得る事はできませんでした。
 このサイトでは1つの表しか存在しないので (0) で取り敢えずは良いのかとは思います。

>あるいは「tournamentTable」を活かすのであれば、「tournamentTable」はidですから、例えば
htmlDoc.getElementById("tournamentTable")(0).innnerText
→ 上記のコードも以前に試してみたのですが、「オブジェクトが必要です。」とのエラーメッセージが出てしまいます。"tournamentTable"を見つけられなかったのでしょう。
 これも、添字を(0)、(1)、(2)と変えてみても同じでした。
 また、Elementsとすると「オブジェクトは、このプロパティまたはメソッドをサポートしていません。」とのエラーメッセージが出てしまいます。

 fujillinさんが指摘されていましたが、基本的にはHTMLのid重複の文法違反に原因があるのかもしれません。

 以上の通りですが、また何か気づいた事があればご指導下さい。

P.S. マクロの細かい部分は残念ながら文字数オーバーでご提示できませんが、次ぎの機会にでも記述できればと考えています。

お礼日時:2021/02/11 10:02

こんにちは



QueryTableの仕様は存じませんが、指定URLでリクエストをしてそのソースから抽出するものではないでしょうか?

ご提示の2番目のURLのシースを見てみるとわかると思いますが、ソースの時点では表の部分は
 <div id="tournamentTable"></div>
となっており、内容が記されていない状態です。
テーブルの下の方を見るとページングがされているので、内容は後から読み込まれているものと推測できます。
まぁ、
><div id="tournamentTable" style="display: block;">
><table class " table-main" id="tournamentTable">
というHTMLも、id重複の文法違反になちゃってますけれど…
もしも、QueryTableがソースから抽出する仕組みになっているのなら、これが原因と推測できます。

内容を取得したいのであれば、後から読み込む仕組みと同様のリクエストを行うか(←サーバ側が受け付けるかどうかは不明)、あるいはブラウザを操作して、一旦表示させてからDOM操作で内容を取得するかではないかと思いますけれど…
(↑ テストしていないので、推測ですけれど)
    • good
    • 0
この回答へのお礼

fujillinさん、迅速なる回答と的確なご指摘を有り難うございました。
 矢張り、OddsPortal 側に問題があるようですね。
 小生、QueryTableを使ったのは初めてなので、これについては殆んど理解できていません。
 お示ししたマクロは殆んど Webからのコピぺです。
 従って、御指摘の「後から読み込む仕組みと同様のリクエストを行う」のは残念ながら手を付けることはできません。
 また、「ブラウザを操作して、一旦表示させてからDOM操作で内容を取得する」点についてはあまり対処したくない方法なのです。
 と云うのも、今回の目的はデータ取得の高速化を狙っており、この方法は適していないように思います(これについて「質問」で触れなかった事をお詫びします)。
 現在はSeleniumBasicとChromeのコンビで以下のようなマクロで目的のテーブルを完全な形で取得できているのですが、Chromeが一つの表を取り込むのに数秒(Chromeの立ち上がり時間を除く)を要し、1サイト当たり2ページの表を100サイト超を巡回すると、データの編集を含めた所要時間が10数分となってしまいます。

Driver.Get (URL)
Driver.FindElementByXPath("//*[@id=""tournamentTable""]/tbody").AsTable().ToExcel (Worksheets("sheet1").Cells(1, 1))

 そこで他に高速化の手段は無いかと探して辿り着いたのが QueryTableだった次第です。
 次善の策としてはHTTPリクエスト(これも全く理解していません)を使った以下のマクロなのですが、当然ながらデータの取り込みができていません(最後の行は完全にNG、文字超過の為、他のコード省略)。

httpReq.Open "GET", URL
Debug.Print htmlDoc.getElementsByTagName("tournamentTable")(0).innerText

 勝手を言って申し訳ないのですが、もし、fujillinさんがお解りであればこれについてもコメントを頂ければ有り難いのですが、宜しくお願いします。

お礼日時:2021/02/06 10:29

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!