核心流程
- 發送
HttpWebRequest 請求目標 URL
- 接收
HttpWebResponse 取得 HTML 原始碼
- 以字串搜尋或正則表達式擷取目標區塊
- 載入
HtmlDocument 解析 DOM 結構
- 遍歷節點提取資料並寫入資料庫
關鍵程式碼實作
1. 取得網頁 HTML 原始碼
using System.Net;
using System.IO;
using System.Text;
private string GetWebContent(string url) {
string result = "";
try {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 30000; // 30 秒逾時
request.Headers.Set("Pragma", "no-cache"); // 禁止快取
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream, Encoding.GetEncoding("GB2312"))) {
result = reader.ReadToEnd();
}
} catch (Exception ex) {
// 實務上建議記錄日誌而非直接 MessageBox
Console.WriteLine($"抓取失敗: {ex.Message}");
}
return result;
}
2. 解析 HTML 並提取表格資料
using System.Windows.Forms; // 需參考 System.Windows.Forms
using System.Data; // DataTable 相關
private void CrawlBaiduTop500() {
string url = "https://list.mp3.baidu.com/topso/mp3topsong.html?id=1#top2";
string html = GetWebContent(url);
// 1. 定位 body 標籤
int bodyStart = html.IndexOf("", tableStart);
string tableHtml = html.Substring(tableStart, tableEnd - tableStart + 8);
// 3. 載入 HtmlDocument 解析
WebBrowser wb = new WebBrowser();
wb.Navigate("about:blank");
HtmlDocument doc = wb.Document.OpenNew(true);
doc.Write(tableHtml);
HtmlElementCollection rows = doc.GetElementsByTagName("TR");
DataTable dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("SongName");
dt.Columns.Add("Singer");
dt.Columns.Add("Flag");
foreach (HtmlElement row in rows) {
HtmlElementCollection cells = row.GetElementsByTagName("TD");
if (cells.Count >= 6) {
// 第一組資料
AddRow(dt, cells[0].InnerText.Replace(".", ""),
ExtractField(cells[1].InnerText, "MusicName"),
ExtractField(cells[1].InnerText, "Singer"));
// 第二組資料
AddRow(dt, cells[2].InnerText.Replace(".", ""),
ExtractField(cells[3].InnerText, "MusicName"),
ExtractField(cells[3].InnerText, "Singer"));
// 第三組資料
AddRow(dt, cells[4].InnerText.Replace(".", ""),
ExtractField(cells[5].InnerText, "MusicName"),
ExtractField(cells[5].InnerText, "Singer"));
}
}
InsertToDatabase(dt);
dataGridView1.DataSource = dt.DefaultView;
}
private void AddRow(DataTable dt, string id, string name, string singer) {
dt.Rows.Add(id, name, singer, "0");
}
private string ExtractField(string source, string fieldName) {
// 依實際 HTML 結構實作解析邏輯
// 此處為示意,需根據實際標記調整
return source;
}
private void InsertToDatabase(DataTable dt) {
// 實作資料庫批次寫入邏輯
}
注意事項與最佳實踐
- 編碼處理:依目標網頁實際編碼設定
Encoding.GetEncoding(...),避免亂碼。
- 例外處理:網路請求務必包裝
try-catch,並記錄錯誤日誌。
- 效能優化:大量抓取時建議使用
HttpClient (現代替代方案) 搭配非同步 async/await。
- 法律合規:請遵守目標網站
robots.txt 及服務條款,避免過度請求導致 IP 被封鎖。
- HtmlDocument 替代方案:生產環境建議使用 HtmlAgilityPack 或 AngleSharp 等專用解析庫,不需依賴 WinForms 元件。