HTMLアジャイルパック - テーブル内のdivのInnerTextを読む

c# html-agility-pack web-scraping

質問

私の問題は、テーブルからdiv InnerTextを取得できないということです。私は正常に別の種類のデータを追加しましたが、テーブルからdivを読み込む方法がわかりません。

次の図ではdivを強調表示しています。この場合はInnerTextを取得する必要があります(番号3)。

最初の写真はここをクリック

私は次のパスを使用してこれを達成しようとしています:

"//div[@class='kal']//table//tr[2]/td[1]/div[@class='cipars']"

しかし、私は次のエラーが発生しています:

エラーメッセージの画像はここをクリック

コードの残りが正しく書かれていると仮定すると、誰かが正しい方向に私を向けることができますか?私はこれを理解しようとしていますが、結果は得られません。

受け入れられた回答

したがって、問題は、XPath内のポジションに依存していることです。ある種のtr 最初の tdがクラスとdivを持つことを期待しているので、これはいくつかのケースではOKですが、ここにはありません。

Chromeのソースを見ると、これは必ずしもそうとは限りません。これは、カレンダーの「1」要素を「2」と「3」と比較することで確認できます。あなたは "1"要素がその周りにいくつかの要素を持っていることに気づくでしょう。他の要素はそうではありません。

元のXPathクエリは要素を返さないため、エラーが発生しています。 HtmlAgilityPackに与えるXPathクエリでDOM要素が生成されない場合は、nullが返されます。

さて、コード全体を表示していないので、このコードがどのように実行されているのか分かりません。しかし、私はあなたがすべてのカレンダーアイテムをループしようとしていると推測しています。いずれにしても、複数の方法がありますが、 descendant XPathセレクタを使用すると、一度にたくさんのロットを取得できます。

//div[@class='kal']//table//descendant::div[@class='cipars']

これにより、 すべてのカレンダー項目(つまり1〜30)が返されます

ただし、特定の行のすべてのアイテムを取得するには、そのtrをクエリにスティックするだけです。

//div[@class='kal']//table//descendant::div[@class='cipars']

これは、2から8(カレンダー項目の2番目の行)を返します。

特定のものをターゲットにするには、ウェブサイトのソースコードを前提にしなければなりません。すべての "cipars" divは、クラスのdatums ....とtd祖先があるように見えるので、あなたの質問から "3"の値を得る:

//div[@class='kal']//table//descendant::div[@class='cipars']

うまくいけば、少なくともこの問題を示すには十分です。

編集

XPathの問題がありますが、別の問題もあります。

サイトは非常に奇妙に作成されています。カレンダーは奇妙な方法で読み込まれます。そのURLにヒットすると、カレンダーは、XML Webサービス(PHPで書かれた)を呼び出すいくつかのJavaScriptによって作成され、カレンダーに使用される完全なtableが計算されます。

これはJavascript(クライアントサイドコード)であるため、HtmlAgilityPackはそれを実行しません。したがって、HtmlAgilityPackはテーブルを「参照」しません。したがって、それに対する照会は「見つからない」(null)として戻ってくる。

これを回避する方法:1)スクリプトを呼び出すツールを使用します。これにより、ブラウザをロードすることを意味します。これに使用するための素晴らしいツールはSeleniumと呼ばれています。これはおそらくサイト全体で使用されるすべてのスクリプティングが実際に呼び出されることを意味するため、全体的に優れたソリューションになるでしょう。それでもXPathを使用することができるので、クエリは変更されません。

2番目の方法は、ページと同じ Webサービスにリクエストを送信することです。これは、基本的に、ページが取得しているのと同じ HTMLを取得し、HtmlAgilityPackでその HTMLを使用することです。どうすればいいの?

C#を使用してデータをWebサービスに簡単にPOSTできます。使用の容易さのために、私はこのSOの質問からコードを盗んだ。これで、ページのリクエストと同じリクエストを送信し、同じHTMLを返すことができます。

だから、いくつかのPOSTデータを送信するには、我々は.....のようなメソッドを生成する

//div[@class='kal']//table//descendant::div[@class='cipars']

私たちはそう呼ぶことができます:

//div[@class='kal']//table//descendant::div[@class='cipars']

どうしたの?さて、私たちが呼んでいるphpファイルは、ページのWebサービスであり、POSTデータもあります。私はそれがサービスに送信するどのようなデータが分かった方法は、(Chromeのデベロッパーコンソールを使用して)Javascriptをデバッグすることです 、あなたはそれがURLにあるほとんど同じことだ気づくことがあります。それは意図的なようだ。

返されるresponseBodyは、カレンダーのtable 物理HTML だけです。

今、私たちは何をしていますか?純粋なHTMLを受け入れることができるので、これをHtmlAgilityPackに読み込みます。

//div[@class='kal']//table//descendant::div[@class='cipars']

さて、私たちは元のXPathを次のように守っています:

//div[@class='kal']//table//descendant::div[@class='cipars']

今、私たちはうまくいけば "3"であるべきものを印刷します:

//div[@class='kal']//table//descendant::div[@class='cipars']

ローカルで実行している私の出力は確かです: 3

しかし、これはあなたが持っている問題を解決するでしょうが、私はサイトの残りの部分がこのようなものであると仮定しています。これが当てはまる場合は、上記の手法を使用して回避することができますが、Seleniumのようなツールがこのような理由で作成されました。




ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ