You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#使用HtmlAgilityPack爬取网站表格及解决空引用异常

C#爬取网页表格并导入PostgreSQL的问题解决

问题根源

  • XPath定位错误:原代码用//*[@id="cr_cashflow"]/div[2]/div/table查找表格,但目标表格的标识是class="cr_dataTable",而非id为cr_cashflow的节点下的表格,导致SelectNodes返回null,后续链式调用触发空引用异常。
  • 未做null校验:即使XPath正确,也可能因网页结构变化、网络问题导致节点找不到,直接调用方法会报错。
  • 使用了过时的WebClient:异步场景下推荐用HttpClient,原生支持async/await。

修正后的异步爬虫代码

先安装HtmlAgilityPack和System.Net.Http NuGet包,替换原有代码:

using HtmlAgilityPack;
using System.Net.Http;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

// 在Form的异步方法中调用(如按钮点击事件标记async)
private async Task FetchTableDataAsync()
{
    string url = "你的目标网站URL";
    List<List<string>> tableData = new List<List<string>>();

    using (HttpClient httpClient = new HttpClient())
    {
        try
        {
            // 异步下载网页内容
            string pageContent = await httpClient.GetStringAsync(url);

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(pageContent);

            // 定位class为cr_dataTable的表格(修正后的XPath)
            var tableNode = doc.DocumentNode.SelectSingleNode("//table[@class='cr_dataTable']");
            
            if (tableNode != null)
            {
                // 遍历表格行,过滤空行
                tableData = tableNode.Descendants("tr")
                    .Where(tr => tr.Elements("td").Count() > 0)
                    .Select(tr => tr.Elements("td")
                        .Select(td => td.InnerText.Trim())
                        .ToList())
                    .ToList();

                // 绑定到DataGridView(注意大小写:DataSource)
                dataGridTable1.DataSource = tableData;
            }
            else
            {
                MessageBox.Show("未找到目标表格");
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"请求出错:{ex.Message}");
        }
    }
}

// 按钮点击事件示例
private async void btnFetch_Click(object sender, EventArgs e)
{
    await FetchTableDataAsync();
}

导出数据到PostgreSQL(pgAdmin对应数据库)

  1. 安装Npgsql NuGet包(PostgreSQL的.NET官方驱动)。
  2. 导入代码示例:
using Npgsql;
using System.Threading.Tasks;

private async Task ImportToPostgreSQLAsync(List<List<string>> tableData)
{
    // 替换为你的数据库连接信息
    string connString = "Host=localhost;Port=5432;Database=你的数据库名;Username=postgres;Password=你的密码";

    using (NpgsqlConnection conn = new NpgsqlConnection(connString))
    {
        await conn.OpenAsync();

        // 假设数据库表结构:CREATE TABLE cash_flow (item TEXT, val1 TEXT, val2 TEXT, val3 TEXT, val4 TEXT);
        foreach (var row in tableData)
        {
            // 根据实际列数调整参数数量
            string sql = @"INSERT INTO cash_flow (item, val1, val2, val3, val4) 
                           VALUES (@item, @val1, @val2, @val3, @val4)";

            using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
            {
                cmd.Parameters.AddWithValue("@item", row[0]);
                cmd.Parameters.AddWithValue("@val1", row[1]);
                cmd.Parameters.AddWithValue("@val2", row[2]);
                cmd.Parameters.AddWithValue("@val3", row[3]);
                cmd.Parameters.AddWithValue("@val4", row[4]);

                await cmd.ExecuteNonQueryAsync();
            }
        }

        MessageBox.Show("数据导入完成");
    }
}

// 调用示例:获取到tableData后执行
// await ImportToPostgreSQLAsync(tableData);

关键注意事项

  • XPath校验:用浏览器开发者工具(F12)定位表格,右键复制XPath/CSS选择器,确保定位准确。
  • 数据清洗:爬取的文本可能含多余空格、逗号,可根据需求转换为数值类型(如int.Parse(row[1].Replace(",", "")))。
  • 异常兜底:网络请求、DOM解析、数据库操作都需加异常捕获,避免程序崩溃。

内容的提问来源于stack exchange,提问作者Sketchup Galaxy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 03:25:18