元の入力HTMLソースをよく見ると、そのデータは、次の'id'属性のいずれかを持つDIVhtml要素である6つの主要なセクションで構成されていることがわかります。" incinterimdiv
" " incannualdiv
" " balinterimdiv
" " balannualdiv
" " casinterimdiv
" " casannualdiv
"。明らかに、これらは、四半期または年次データの損益計算書、貸借対照表、およびキャッシュフローと一致します。
ここで、Html Agility Packを使用してサイトをスクレイピングする場合、Html Agility PackはHTMLを介したプレーンなXPATHをサポートしているため、XMLに依存せずにHTMLコード内の任意のノードに到達する最も簡単な方法であるXPATHを使用することをお勧めします。
XPATHは確かに学習する必要がありますが、1行で非常に多くのことを実行するため、非常にエレガントです。これは新しいクールなC#指向のXLinq構文では古風に見えるかもしれませんが:)、XPATHははるかに簡潔です。また、コードと入力HTMLの間のバインディングを単純な古い文字列に集中させ、入力ソースが進化したとき(たとえば、IDが変更されたとき)にコードが再コンパイルされないようにすることもできます。これにより、スクレイピングコードがより堅牢になり、将来にわたって利用できるようになります。XPATHバインディングをXSL(T)ファイルに入れて、HTMLをXMLとして表示されるデータに変換できるようにすることもできます。
とにかく、十分な余談:)これは、特定の行タイトルから財務データを取得できるサンプルコードと、すべての行(6つの主要セクションの1つから)からすべてのデータを取得できるサンプルコードです。
HtmlWeb web = new HtmlWeb();
HtmlDocument doc = web.Load("http://www.google.com/finance?q=NASDAQ:TXN&fstype=ii");
// How get a specific line:
// 1) recursively get all DIV elements with the 'id' attribute set to 'casannualdiv'
// 2) get all TABLE elements under, with the 'id' attribute set to 'fs-table'
// 3) recursively get all TD elements containing the given text (trimmed)
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//div[@id='casannualdiv']/table[@id='fs-table']//td[normalize-space(text()) = 'Deferred Taxes']"))
{
Console.WriteLine("Title:" + node.InnerHtml.Trim());
// get all following sibling TD elements
foreach (HtmlNode sibling in node.SelectNodes("following-sibling::td"))
{
Console.WriteLine(" data:" + sibling.InnerText.Trim()); // InnerText works also for negative values
}
}
// How to get all lines:
// 1) recursively get all DIV elements with the 'id' attribute set to 'casannualdiv'
// 2) get all TABLE elements under, with the 'id' attribute set to 'fs-table'
// 3) recursively get all TD elements containing the class 'lft lm'
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//div[@id='casannualdiv']/table[@id='fs-table']//td[@class='lft lm']"))
{
Console.WriteLine("Title:" + node.InnerHtml.Trim());
foreach (HtmlNode sibling in node.SelectNodes("following-sibling::td"))
{
Console.WriteLine(" data:" + sibling.InnerText.Trim());
}
}