【问题标题】:Scraping specific pieces of data from website in C# using HtmlAgilityPack使用 HtmlAgilityPack 从 C# 中的网站抓取特定数据
【发布时间】:2020-11-24 20:37:51
【问题描述】:

我很想使用 HtmlAgilityPack 为某个嵌套的 div 类抓取网页,该类包含带有我要提取的数据的 span 标签

我想要的元素文本的完整 XPath:

/html/body/div[2]/div/div[1]/div/table/tbody/tr/td/span

我的代码:

  static void Main(string[] args)
        {
            HtmlAgilityPack.HtmlWeb web = new HtmlAgilityPack.HtmlWeb();
            HtmlAgilityPack.HtmlDocument doc = web.Load("http://watchout4snakes.com/wo4snakes/Random/RandomParagraph");

            var paragraph = doc.DocumentNode.SelectNodes("//div[@class='mainBody']//div[@class='content']//div[@class='resultContainer']" +
                "//div[@class='resultBox']//table[@class='paragraphResult']").ToList();

            foreach (var item in paragraph)
            {
                Console.WriteLine(item.InnerText);
            }
        }

我尝试将完整的 XPath 放入 doc.DocumentNode.SelectNodes() 以及只是 Xpath //*[@id='result'] 我的问题是它要么不返回任何内容,要么在doc.DocumentNode.SelectNodes() 行上收到错误消息Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'source')

【问题讨论】:

    标签: c# html web-scraping html-agility-pack


    【解决方案1】:

    问题来源是Paragraph是通过AJAX加载的,页面加载后由JS脚本加载。如果你在浏览器中打开开发工具/网络,你可以看到。

    加载的页面部分如下所示

    <table class="paragraphResult">
        <tr>
            <td>
                <span id="result"></span>
            </td>
        </tr>
    </table>
    

    里面什么都没有。

    加载后,页面将 AJAX POST 请求发送到相同的 URL 并获取带有参数的纯字符串

    Subject1: "",
    Subject2: ""
    

    以及它在 URL 编码格式中的外观

    Subject1=&Subject2=
    

    要模拟表单行为,您可以手动发送 POST 请求。 HtmlAgilityPack 在这里没用,因为接收到的数据只是一个普通的字符串。

    class Program
    {
        private static readonly HttpClient client = new HttpClient();
    
        static async Task Main(string[] args)
        {
            Console.Write("Proper Noun 1: ");
            string subject1 = Console.ReadLine();
            Console.Write("Proper Noun 2: ");
            string subject2 = Console.ReadLine();
            Dictionary<string, string> parameters = new Dictionary<string, string>()
            {
                { "Subject1", subject1 },
                { "Subject2", subject2 }
            };
            try
            {
                string result = await PostHTTPRequestAsync("http://watchout4snakes.com/wo4snakes/Random/RandomParagraph", parameters);
                Console.WriteLine(result);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadKey();
        }
    
        private static async Task<string> PostHTTPRequestAsync(string url, Dictionary<string, string> data)
        {
            using (HttpContent formContent = new FormUrlEncodedContent(data))
            using (HttpResponseMessage response = await client.PostAsync(url, formContent).ConfigureAwait(false))
            {
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            }
        }
    }
    

    控制台输出

    Proper Noun 1: test
    Proper Noun 2: StackOverflow
    When will the bass garage StackOverflow? A digest sighs test below the objective card. Why won't test finish behind a girlfriend? A heating science approaches test.
    

    效果很好。您只需要正确分析浏览器中的 HTTP 流量即可。 HttpClient 也是与网络交互的强大工具。

    【讨论】:

      猜你喜欢
      • 2019-01-18
      • 1970-01-01
      • 1970-01-01
      • 2022-07-10
      • 1970-01-01
      • 2015-11-15
      • 1970-01-01
      • 1970-01-01
      • 2021-06-20
      相关资源
      最近更新 更多