HTML Agility Pack:解析href标签

23

如何有效地解析这个标签的 href 属性值:

<tr>
<td rowspan="1" colspan="1">7</td>
<td rowspan="1" colspan="1">
<a class="undMe" href="/ice/player.htm?id=8475179" rel="skaterLinkData" shape="rect">D. Kulikov</a>
</td>
<td rowspan="1" colspan="1">D</td>
<td rowspan="1" colspan="1">0</td>
<td rowspan="1" colspan="1">0</td>
<td rowspan="1" colspan="1">0</td>
[...]

我想获取玩家ID,即:8475179。这是我目前的代码:

        // Iterate all rows (players)
        for (int i = 1; i < rows.Count; ++i)
        {
            HtmlNodeCollection cols = rows[i].SelectNodes(".//td");

            // new player
            Dim_Player player = new Dim_Player();

                // Iterate all columns in this row
                for (int j = 1; j < 6; ++j)
                {
                    switch (j) {
                        case 1: player.Name = cols[j].InnerText;
                                player.Player_id = Int32.Parse(/* this is where I want to parse the href value */); 
                                break;
                        case 2: player.Position = cols[j].InnerText; break;
                        case 3: stats.Goals = Int32.Parse(cols[j].InnerText); break;
                        case 4: stats.Assists = Int32.Parse(cols[j].InnerText); break;
                        case 5: stats.Points = Int32.Parse(cols[j].InnerText); break;
                    }
                }

如果您在switch中使用硬编码索引,为什么要使用for循环呢?为什么不使用player.Position = cols[2].InnerText;呢? - Paul Tyng
好的观点。我正在回收我写过的一些旧代码,所以我没有考虑到那个问题。 - Jean-François Beaulieu
2个回答

39

根据你的示例,这对我起作用了:

HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.Load("test.html");
var link = htmlDoc.DocumentNode
                  .Descendants("a")
                  .First(x => x.Attributes["class"] != null 
                           && x.Attributes["class"].Value == "undMe");

string hrefValue = link.Attributes["href"].Value;
long playerId = Convert.ToInt64(hrefValue.Split('=')[1]);

在实际使用中,您需要添加错误检查等。


我也可以工作!难道只有我觉得这很不方便吗?因为我们必须使用htmlDoc来查找所有类为“undMe”的节点,而实际上我们可以使用cols[j],它的InnerHtml中有href - Jean-François Beaulieu
你对链接的位置做出了非常强烈的假设 - 这可能有效,但非常死板且容易出错,例如如果您添加另一列。所提出的方法不会出现这种情况,因为它在最小的假设上进行查询以获取链接。 - BrokenGlass
实际上,这个问题的唯一问题是 First() 是静态的,并且总是获取它找到的第一个元素。我需要一些动态的东西,可以获取实际的元素。 - Jean-François Beaulieu
啊...找到了:var link = cols.Descendants("a").First(); 因为我只想在已经找到的列中搜索。 - Jean-François Beaulieu
这是一个很棒的答案...它完美地运行了。唯一的问题是将“.First”替换为“.FirstOrDefault”,否则它会抛出异常。 - Zia Ur Rahman
很棒的答案。+1 - AndyUK

4

使用XPath表达式来查找:

 foreach (HtmlNode link in doc.DocumentNode.SelectNodes("//a[@class='undMe']"))
 {
      HtmlAttribute att = link.Attributes["href"];
      Console.WriteLine(new Regex(@"(?<=[\?&]id=)\d+(?=\&|\#|$)").Match(att.Value).Value);
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接