-
使用
HtmlAgilityPack(推荐):这是一个非常强大和灵活的 HTML 解析库,它不像正则表达式那样脆弱,能够正确处理格式不规范的 HTML,并且提供了类似 XPath 的查询方式,可以精确地定位和提取你需要的元素,这是处理复杂网页结构的首选方案。
(图片来源网络,侵删) -
使用
WebBrowser控件:这种方法模拟了用户在浏览器中的操作,它会加载整个网页,包括执行其中的 JavaScript 脚本,然后你可以像操作普通 Windows 窗体控件一样去访问 DOM 元素,这种方法适用于那些数据是动态加载(通过 JavaScript)的网页,但实现起来相对复杂。
下面我将详细介绍这两种方法,并提供完整的代码示例。
使用 HtmlAgilityPack (最常用、最推荐)
这种方法的核心思想是:下载网页的 HTML 源代码 -> 使用 HtmlAgilityPack 将其解析成一个可导航的文档树 -> 使用 XPath 定位到表格 -> 遍历表格的行和列,提取数据。
步骤 1: 安装 HtmlAgilityPack
如果你使用的是 Visual Studio,可以通过 NuGet 包管理器轻松安装。

(图片来源网络,侵删)
- 在“解决方案资源管理器”中右键点击你的项目。
- 选择“管理 NuGet 程序包...”。
- 在“浏览”选项卡中搜索
HtmlAgilityPack。 - 点击“安装”。
步骤 2: 编写 VB.NET 代码
以下是一个完整的示例,它从一个公开的测试网站抓取一个表格,并将数据显示在 DataGridView 控件中。
示例目标网页:我们使用一个经典的测试表格页面 http://www.w3schools.com/html/html_tables.asp 上的第一个表格。
VB.NET 代码示例:
Imports System.Net
Imports System.IO
Imports HtmlAgilityPack
Public Class Form1
Private Async Sub btnFetchTable_Click(sender As Object, e As EventArgs) Handles btnFetchTable.Click
' 禁用按钮,防止重复点击
btnFetchTable.Enabled = False
btnFetchTable.Text = "抓取中..."
' 使用异步方法来避免界面卡顿
Await Task.Run(Sub()
Try
' 1. 定义目标网页 URL
Dim url As String = "https://www.w3schools.com/html/html_tables.asp"
' 2. 创建 WebClient 并设置 User-Agent,模拟浏览器访问
Using client As New WebClient()
client.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3")
' 3. 下载网页 HTML 源代码
Dim html As String = client.DownloadString(url)
' 4. 创建 HtmlDocument 对象并加载 HTML
Dim doc As New HtmlDocument()
doc.LoadHtml(html)
' 5. 使用 XPath 定位到目标表格
' 通过分析网页,我们可以找到第一个表格的 XPath
Dim tableNode As HtmlNode = doc.DocumentNode.SelectSingleNode("//div[@class='w3-example']/table")
If tableNode IsNot Nothing Then
' 6. 解析表格数据
Dim tableData As New DataTable()
' 获取表头
Dim headerRow As HtmlNode = tableNode.SelectSingleNode("tr")
If headerRow IsNot Nothing Then
For Each headerCell As HtmlNode In headerRow.SelectNodes("th|td")
tableData.Columns.Add(headerCell.InnerText.Trim())
Next
End If
' 获取表体数据
Dim dataRows As HtmlNodeCollection = tableNode.SelectNodes("tr[position()>1]")
If dataRows IsNot Nothing Then
For Each dataRow As HtmlNode In dataRows
Dim rowValues As New List(Of String)()
For Each dataCell As HtmlNode In dataRow.SelectNodes("td|th")
rowValues.Add(dataCell.InnerText.Trim())
Next
If rowValues.Count = tableData.Columns.Count Then
tableData.Rows.Add(rowValues.ToArray())
End If
Next
End If
' 7. 在 UI 线程上更新 DataGridView
Me.Invoke(Sub()
DataGridView1.DataSource = tableData
DataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
End Sub)
Else
Me.Invoke(Sub()
MessageBox.Show("未找到目标表格,请检查 XPath 是否正确。")
End Sub)
End If
End Using
Catch ex As Exception
' 在 UI 线程上显示错误信息
Me.Invoke(Sub()
MessageBox.Show("发生错误: " & ex.Message)
End Sub)
Finally
' 恢复按钮状态
Me.Invoke(Sub()
btnFetchTable.Enabled = True
btnFetchTable.Text = "抓取表格"
End Sub)
End Try
End Sub)
End Sub
End Class
代码解释:
- Imports:引入了必要的命名空间。
- 异步操作 (
Async/Await):网络请求和 HTML 解析可能会比较耗时,放在Task.Run中可以防止在抓取过程中你的应用程序界面(UI)失去响应。 - WebClient:用于从指定 URL 下载网页内容,设置
User-Agent可以避免被一些网站识别为爬虫而拒绝访问。 - HtmlDocument:
HtmlAgilityPack的核心类,用于加载和解析 HTML。 SelectSingleNode/SelectNodes:这是最关键的部分,它们使用 XPath 表达式来查找节点。//div[@class='w3-example']/table:这个 XPath 的意思是“在文档的任何位置,找到一个class属性为w3-example的div元素,然后在这个div内部找到第一个table元素”,这是定位特定表格的强大方法。tr[position()>1]:选择表格中所有第二个及之后的行(tr元素),即跳过表头行。th|td:选择所有的表头单元格 (th) 或普通数据单元格 (td)。
DataTable:我们将解析出的数据存储在DataTable中,因为它可以非常方便地绑定到DataGridView控件。Me.Invoke:因为后台线程不能直接操作 UI 控件,所以必须使用Invoke方法,将更新界面的代码切换到主 UI 线程上执行。
使用 WebBrowser 控件
这种方法模拟了浏览器行为,特别适合那些数据是通过 JavaScript 动态加载的网站。

(图片来源网络,侵删)
步骤 1: 添加 WebBrowser 控件
- 打开你的 Windows 窗体设计器。
- 从“工具箱”中拖拽一个
WebBrowser控件到窗体上(可以命名为WebBrowser1)。 - 再拖拽一个
Button控件(命名为btnLoadAndParse)和一个DataGridView控件。
步骤 2: 编写 VB.NET 代码
Imports System.Threading.Tasks
Public Class Form2
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' 禁用 WebBrowser 的右键菜单和脚本错误提示
WebBrowser1.IsWebBrowserContextMenuEnabled = False
WebBrowser1.ScriptErrorsSuppressed = True
End Sub
Private Sub btnLoadAndParse_Click(sender As Object, e As EventArgs) Handles btnLoadAndParse.Click
' 添加事件处理程序,当网页加载完成时执行我们的解析逻辑
AddHandler WebBrowser1.DocumentCompleted, AddressOf WebBrowser1_DocumentCompleted
' 导航到目标网页
WebBrowser1.Navigate("https://www.w3schools.com/html/html_tables.asp")
End Sub
Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs)
' 移除事件处理程序,防止重复添加
RemoveHandler WebBrowser1.DocumentCompleted, AddressOf WebBrowser1_DocumentCompleted
' 现在可以安全地访问网页的 DOM 了
ParseTableFromWebBrowser()
End Sub
Private Sub ParseTableFromWebBrowser()
Try
' 获取网页的文档对象
Dim doc As HtmlDocument = WebBrowser1.Document
' 在 DOM 中查找表格 (这里我们使用一个简单的选择器,实际中可能需要更复杂的定位)
' 通过 Name 来查找是常见做法,前提是你知道表格的 ID 或 Name
' 假设我们不知道,就通过索引来获取第一个表格
If doc.All.GetElementsByTagName("table").Count > 0 Then
Dim htmlTable As HtmlElement = doc.All.GetElementsByTagName("table")(0)
' 创建一个 DataTable 来存储数据
Dim tableData As New DataTable()
' 解析表头
Dim headerRow As HtmlElement = htmlTable.GetElementsByTagName("tr")(0)
For Each headerCell As HtmlElement In headerRow.GetElementsByTagName("th")
tableData.Columns.Add(headerCell.InnerText.Trim())
Next
' 解析表体数据
For i As Integer = 1 To htmlTable.GetElementsByTagName("tr").Count - 1
Dim dataRow As HtmlElement = htmlTable.GetElementsByTagName("tr")(i)
Dim rowValues As New List(Of String)()
For Each dataCell As HtmlElement In dataRow.GetElementsByTagName("td")
rowValues.Add(dataCell.InnerText.Trim())
Next
' 确保行的列数与表头匹配
If rowValues.Count = tableData.Columns.Count Then
tableData.Rows.Add(rowValues.ToArray())
End If
Next
' 绑定数据到 DataGridView
DataGridView1.DataSource = tableData
DataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
Else
MessageBox.Show("未在页面中找到任何表格。")
End If
Catch ex As Exception
MessageBox.Show("解析时发生错误: " & ex.Message)
End Try
End Sub
End Class
代码解释:
WebBrowser1.Navigate:开始加载指定的网页。DocumentCompleted事件:这个事件在网页及其所有资源(如图片、脚本)加载完毕后触发,这是执行我们解析逻辑的最佳时机。WebBrowser1.Document:获取一个代表当前已加载网页的HtmlDocument对象,这个对象的结构和你在 JavaScript 中访问document对象非常相似。GetElementsByTagName("table"):获取页面中所有的table元素,我们这里取第一个(0)作为示例。- 遍历
tr和td:与HtmlAgilityPack的逻辑类似,我们逐行逐列地读取数据并填充到DataTable中。
总结与对比
| 特性 | HtmlAgilityPack |
WebBrowser 控件 |
|---|---|---|
| 工作原理 | 解析静态 HTML 源码 | 模拟浏览器,渲染完整页面并执行 JS |
| 性能 | 快,无需加载资源,不执行 JS | 慢,需要完整加载页面和执行 JS |
| 适用场景 | 静态网页,或数据最终在 HTML 源码中可见的页面 | 动态网页,数据由 JavaScript 动态生成或加载 |
| 依赖 | 需要通过 NuGet 安装库 | .NET Framework 自带控件,无需额外安装 |
| 易用性 | XPath 非常强大,学习曲线稍陡 | 类似于 DOM 操作,对前端开发者友好 |
| 资源占用 | 低 | 高,会启动一个完整的浏览器进程 |
如何选择?
- 首选
HtmlAgilityPack:对于 90% 的网页抓取需求,HtmlAgilityPack都是最佳选择,它速度快、资源占用少、功能强大。 - 当
HtmlAgilityPack失败时再考虑WebBrowser:如果你发现用HtmlAgilityPack抓取不到数据,那很可能是数据由 JS 动态加载的,这时,你才应该使用WebBrowser控件来模拟真实用户访问,等待 JS 执行完毕后再抓取。
希望这个详细的教程能帮助你在 VB.NET 项目中成功抓取网页表格!
