如何在 C# 中提取特定的 link?

How to extract specific link in c#?

我正在使用 HtmlAgilitypack 从以下网站提取一些数据:

 <div class="pull-right">
          <ul class="list-inline">
            <li class="social">
              <a target="_blank" href="https://www.facebook.com/wsat.a?ref=ts&amp;fref=ts" class="">
                <i class="icon fa fa-facebook" aria-hidden="true"></i>
              </a>
            </li>
            <li class="social">
              <a target="_blank" href="https://twitter.com/wsat_News" class="">
                <i class="icon fa fa-twitter" aria-hidden="true"></i>
              </a>
            </li>
            <li>
                <a href="/user" class="hide">
                <i class=" icon fa fa-user" aria-hidden="true"></i>
              </a>
            </li>
            <li>
              <a onclick="ga('send', 'event', 'PDF', 'Download', '');" href="https://wsat.com/pdf/issue15170/index.html" target="_blank" class="">

                PDF
                <i class="icon fa fa-file-pdf-o" aria-hidden="true"></i>
              </a>
            </li>

我已经成功地编写了这段代码来提取 html 脚本中的第一个 link,即 https://www.facebook.com/wsat。但是,我只想用 pdf 提取 link https://wsat.com/pdf/issue15170/index.html 但没有任何运气。如何指定要提取的 link?

        var url = "https://wsat.com/";
        var HttpClient = new HttpClient();
        var html = await HttpClient.GetStringAsync(url);
        var htmlDocument = new HtmlDocument();
        htmlDocument.LoadHtml(html);


        var links = htmlDocument.DocumentNode.Descendants("div").Where(node => node.GetAttributeValue("class", "").Equals("pull-right")).ToList();

        var alink = links.First().Descendants("a").FirstOrDefault().ChildAttributes("href")?.FirstOrDefault().Value;

        await Launcher.OpenAsync(alink);

在您的查询中 Descendants("a") 选择了根 div 中的所有 link。在 FirstOrDefault() returns 之后,您只是第一个 link。所以你可以做的是将每个 link 映射到它的 href,然后对集合使用字符串操作来找到合适的。

        var alink = links.First().Descendants("a")
            .Select(node => node.ChildAttributes("href").FirstOrDefault()?.Value)
            .Where(s => !string.IsNullOrEmpty(s))
            .ToList();
        foreach (var l in alink)
        {
            Console.WriteLine(l);
        }
        Console.WriteLine();

        var wsatCom = alink.FirstOrDefault(s => s.StartsWith("https://wsat.com"));
        Console.WriteLine(wsatCom);

此外。 ?. 运算符需要在 FirstOrDefault() 之后而不是之前,如果你想处理没有 href 的 links。我相信在那种情况下 ChildAttributes("href") returns 空集合,FirstOrDefault returns null,并且你有空引用异常。

使用 xpath 表达式作为选择器:

var alink = htmlDocument.DocumentNode
    .SelectSingleNode("//li/a[contains(@onclick, 'PDF')]")
    .GetAttributeValue("href", "");

xpath 说明(按要求):

将文档中任意深度的 li 标记与直接子 a 标记匹配,该标记的属性 onclick 包含字符串 'PDF'.

Regex 可以帮助您吗?我认为这比使用 HTML 敏捷包遍历链接要容易得多,而且感觉不像是幸运的机会。

using System;
using System.Text.RegularExpressions;

public class Example
{
    public static void Main()
    {
        string pattern = @"https:\/\/wsat\.com\/[\w\-\.]+[^#?\s][^""]+";
        string input = @"<div class=""pull-right"">
          <ul class=""list-inline"">
            <li class=""social"">
              <a target=""_blank"" href=""https://www.facebook.com/wsat.a?ref=ts&amp;fref=ts"" class="""">
                <i class=""icon fa fa-facebook"" aria-hidden=""true""></i>
              </a>
            </li>
            <li class=""social"">
              <a target=""_blank"" href=""https://twitter.com/wsat_News"" class="""">
                <i class=""icon fa fa-twitter"" aria-hidden=""true""></i>
              </a>
            </li>
            <li>
                <a href=""/user"" class=""hide"">
                <i class="" icon fa fa-user"" aria-hidden=""true""></i>
              </a>
            </li>
            <li>
              <a onclick=""ga('send', 'event', 'PDF', 'Download', '');"" href=""https://wsat.com/pdf/issue15170/index.html"" target=""_blank"" class="""">

                PDF
                <i class=""icon fa fa-file-pdf-o"" aria-hidden=""true""></i>
              </a>
            </li>";
        RegexOptions options = RegexOptions.Multiline;

        foreach (Match m in Regex.Matches(input, pattern, options))
        {
            Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
        }
    }
}

对于这种工作,我建议使用 AngleSharp 它允许您使用 css select 或 select 任何您需要的元素。

var doc = new HtmlParser().ParseDocument(myHtml);
var pdfUrl = doc.QuerySelector("ul.list-inline a:nth-child(4)").GetAttribute("href");

var links = doc.QuerySelectorAll("ul.list-inline a").Where(a=> a.GetAttribute("href").StartsWith("https://wsat.com/pdf/")).ToList();

好处是您可以随时测试您的 select 或在任何浏览器开发人员控制台中,而无需 code/compile 您的 C#