【问题标题】:HTML Agility pack: parsing an href tagHTML 敏捷包:解析 href 标签
【发布时间】:2012-01-19 19:49:00
【问题描述】:

我将如何有效地从中解析 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;
  • 好点。我正在回收我写的一些旧代码,所以我没有想到。

标签: c# asp.net-mvc-3 html-parsing html-agility-pack


【解决方案1】:

使用 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);
 }

【讨论】:

    【解决方案2】:

    根据您的示例,这对我有用:

    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
    • 您对链接的位置做出了非常强烈的假设 - 这可能工作正常,但非常僵化并且会中断,即如果您添加另一列。所提出的方法不会因为它在最小假设下查询链接
    • 实际上,唯一的问题是First(),它是静态的,总是带来他找到的第一个元素。我需要一些动态的东西来获取实际元素。
    • 啊……找到了:var link = cols.Descendants("a").First();,因为我只想在我已经找到的列中搜索。
    • 这是一个很棒的答案......它工作得很好。唯一的问题是将 .First 替换为 .FirstOrDefault ,否则会抛出异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    • 2017-06-01
    • 2023-03-25
    相关资源
    最近更新 更多