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对应数据库)
- 安装
NpgsqlNuGet包(PostgreSQL的.NET官方驱动)。 - 导入代码示例:
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
相关产品推荐
相关产品推荐

