我的主函数中有这个代码,我只想解析表格的第一行(例如2017年11月7日73.78 74.00 72.32 72.71 17,245,947)。
我创建了一个只结束第一行的节点,但是当我开始调试时,节点值为null。如何解析这些数据并将其存储在例如字符串或单个变量中。有办法吗?
WebClient web = new WebClient();
string page = web.DownloadString("https://finance.google.com/finance/historical?q=NYSE:C&ei=7O4nV9GdJcHomAG02L_wCw");
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(page);
var node = doc.DocumentNode.SelectSingleNode("//*[@id=\"prices\"]/table/tbody/tr[2]");
List<List<string>> node = doc.DocumentNode.SelectSingleNode("//*[@id=\"prices\"]/table").Descendants("tr").Skip(1).Where(tr => tr.Elements("td").Count() > 1).Select(tr => tr.Elements("td").Select(td=>td.InnerText.Trim()).ToList()).ToList() ;
答案 0 :(得分:1)
您的选择XPath字符串似乎有错误。由于tbody
是生成的节点,因此不应包含在路径中:
//*[@id=\"prices\"]/table/tr[2]
虽然这应该读取值HtmlAgilityPack遇到另一个问题malformed html
。解析文本中的所有<tr>
和<td>
节点都没有相应的</tr>
或</td>
结束标记,并且HtmlAgitilityPack无法从包含格式错误的行的表中选择值。因此,有必要在第一步中选择整个表格:
//*[@id=\"prices\"]/table
在下一步中,通过添加</tr>
和</td>
结束标记来清理HTML并使用更正的表重复解析或使用提取的字符串进行手工解析 - 只需从表字符串中提取第10行到第15行并将它们分成>
个字符。原始解析如下所示。代码经过测试和运行。
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
namespace GoogleFinanceDataScraper
{
class Program
{
static void Main(string[] args)
{
WebClient web = new WebClient();
string page = web.DownloadString("https://finance.google.com/finance/historical?q=NYSE:C&ei=7O4nV9GdJcHomAG02L_wCw");
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(page);
var node = doc.DocumentNode.SelectSingleNode("//div[@id='prices']/table");
string outerHtml = node.OuterHtml;
List<String> data = new List<string>();
using(StringReader reader = new StringReader(outerHtml))
{
for(int i = 0; ; i++)
{
var line = reader.ReadLine();
if (i < 9) continue;
else if (i < 15)
{
var dataRawArray = line.Split(new char[] { '>' });
var value = dataRawArray[1];
data.Add(value);
}
else break;
}
}
Console.WriteLine($"{data[0]}, {data[1]}, {data[2]}, {data[3]}, {data[4]}, {data[5]}");
}
}
}