2012-05-23 34 views
3

我期待從link執行Web數據抽取

我已經安裝了HTMLAgilityPack得到今天的價格,但我無法掌握,一旦捕捉文件表如何extracct其第一個TD元素包含在格式DD今天的日期行-mmm-yy

任何人都可以通過代碼片段指向正確的方向嗎?

目前我有:

HtmlDocument doc = new HtmlDocument(); 
doc.Load("http://lbma.org.uk/pages/printerFriendly.cfm?thisURL=index.cfm&title=gold_fixings&page_id=53&show=2012&type=daily"); 

foreach(HtmlNode tr in doc.DocumentNode.SelectNodes("tr")) 
{ 

} 

回答

0

您需要在XPath的閱讀起來。我仍然在學習自己,所以可能會有比這更好的路徑聲明,但是您需要做類似的事情:

foreach(HtmlNode tr in doc.DocumentNode.SelectNodes("tr[td[1] = '03-Jan-12']")) 
{ 

}  
+0

謝謝...獲取以下錯誤。錯誤'HtmlAgilityPack。HtmlNodeCollection'不包含'ParentNode'的定義,並且沒有找到接受'HtmlAgilityPack.HtmlNodeCollection'類型的第一個參數的擴展方法'ParentNode'(你缺少using指令還是程序集引用?) – Gravy

+0

@Gravy糟糕。我正在使用SelectNode進行測試,而不是SelectNodes。這個更新的代碼是否工作?我沒有安裝HtmlAgilityPack,所以我只是用XmlDocument對象進行測試。所以我只是假設一個HtmlNode有一個ParentNode屬性。 –

+0

謝謝你。我現在有第二個問題... HtmlDocument doc = new HtmlDocument(); doc.Load(「http://lbma.org.uk/pages/printerFriendly.cfm?thisURL=index.cfm&title=gold_fixings&page_id=53&show=2012&type=daily」);是不可能的,因爲它不喜歡讀取遠程URL ...我怎樣才能從遠程URL生成一個HtmlDocument? – Gravy

1

好玩。該頁面的Html格式很糟糕,所以我可以看到你的問題。不過,我不會用10英尺的杆子接觸XPath。 Linq讓生活變得如此簡單。

HtmlWeb web = new HtmlWeb(); 
HtmlDocument doc = web.Load("http://lbma.org.uk/pages/printerFriendly.cfm?thisURL=index.cfm&title=gold_fixings&page_id=53&show=2012&type=daily"); 

HtmlNode todaysRow = doc.DocumentNode.Descendants("tr").Where(n => n.InnerText.StartsWith(string.Format("{0:dd-MMM-yy}", DateTime.Today), StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); 
if (todaysRow != null) 
{ 
    List<HtmlNode> cells = todaysRow.Descendants("td").ToList(); 
    decimal usd = decimal.Parse(cells[1].FirstChild.InnerText); 
    decimal gbp = decimal.Parse(cells[2].FirstChild.InnerText); 
    // ... etc 
} 
+0

+1優雅的Linq解決方案。 – gfppaste

0

嘗試了這一點:

Dictionary<string, string> values = new Dictionary<string, string>(); 
string key, date; 
HtmlDocument doc = Load(html); 
HtmlNode node = doc.DocumentNode.SelectSingleNode(".//table[@class='pricing detail']"); 
//this will pull out only the dates, and store them in variable 'date' 
foreach(HtmlNode child in node.SelectNodes(".//tr[@class='left']") 
{ 
    date = child.GetInnerText; 
} 
//this will pull out the dates and the prices, and put them into a mapped data structure for easy (and quick!) referencing 
foreach(HtmlNode child in node.SelectNodes(".//tr") 
{ 
    if(child.Attributes.contains("class")) 
    { 
     key = child.GetInnerText; 
    } 
    else 
    { 
     values.Add(key, child.GetInnerText); 
    } 
} 

那麼它只是一個把你的文字到一個數組或字符串構成你的字典的問題。

說明: 基本上,foreach()位代碼將只在您的表中查找匹配<tr>屬性的子表。然後通過節點集合進行迭代,並檢查節點是否爲日期(即節點是否與屬性<table class="pricing detail">匹配。如果是,則將此節點的值(GetInnerText位)用作字典鍵(即日期)如果比較結果爲假,則代碼會將後續子節點值添加到字典中,映射到日期鍵,直到日期鍵更改爲止。

用於從字典中遷移值到輸出,我是積極的,你可以做到這一點

在格式化你的日期方面,見Jacob's answer,他做得非常好,儘管看起來日期已經按照你希望的方式進行了格式化。

我在這裏提供了兩個foreach循環:第一個做你想做的事(只是從網站上截取日期)。在我完全理解你所問的內容之前,我確實寫了第二篇,但如果你想使用它,我會留下它。

注意 我故意沒有使這個代碼靈活...它非常嚴格地附加到HTML的結構。我之所以這麼做是因爲以下幾個原因:第一,學習如何有效刮擦的最好方法是被迫編寫靈活的刮刀,每次使用後都不必完全停用。我知道我站在一個肥皂盒上,但是一旦你真正掌握了一些信息挖掘的原則,你會發現你的程序會更容易,更流暢,而且我敢說... funner ...編寫和維護。第二個是,我想鼓勵你真正探索htmlagilitypack提供的功能。它真的是一個令人印象深刻的圖書館,更值得花時間去玩。