我正在尝试遍历网页(http://www.oddschecker.com/golf/the-masters/winner)上可变长度表的每一行并提取一些数据
问题是我似乎无法捕获空引用并在不引发异常的情况下终止循环!
int i = 1;
bool test = string.IsNullOrEmpty(doc.DocumentNode.SelectNodes(String.Format("//*[@id='t1']/tr[{0}]/td[3]/a[2]", i))[0].InnerText);
while (test != true)
{
string name = doc.DocumentNode.SelectNodes(String.Format("//*[@id='t1']/tr[{0}]/td[3]/a[2]", i))[0].InnerText;
//extract data
i++;
}
try-catch 语句也没有抓住它:
bool test = false;
try
{
string golfersName = doc.DocumentNode.SelectNodes(String.Format("//*[@id='t1']/tr[{0}]/td[3]/a[2]", i))[0].InnerText;
}
catch
{
test = true;
}
while (test != true)
{
...
代码逻辑有点不对劲。使用原始代码,如果test
true
计算,循环将永远不会终止。似乎您想在每次循环迭代中检查,而不是在开始时只检查一次。
无论如何,有一个更好的方法。您可以选择所有相关节点,而无需指定每个<tr>
索引,并使用foreach
遍历节点集:
var nodes = doc.DocumentNode.SelectNodes("//*[@id='t1']/tr/td[3]/a[2]");
foreach(HtmlNode node in nodes)
{
string name = node.InnerText;
//extract data
}
或者使用循环for
而不是foreach
,如果每个节点的索引对于"提取数据"过程是必需的:
for(i=1; i<=nodes.Count; i++)
{
//array index starts from 0, unlike XPath element index
string name = nodes[i-1].InnerText;
//extract data
}
旁注:要查询单个元素,您可以使用SelectSingleNode("...")
而不是SelectNodes("...")[0]
。如果没有节点与 XPath 条件匹配,这两种方法都返回 null
,因此您可以根据返回的原始值而不是InnerText
属性进行检查以避免异常:
var node = doc.DocumentNode.SelectSingleNode("...");
if(node != null)
{
//do something
}