目前筆者知道的 C# 抓取網頁資料的第三方套件最大的兩個是 AngleSharp 和 HtmlAgilityPack
簡易比較如下:
(統計時間: 2023-03-22)
雖然 HtmlAgilityPack 下載量比較多,但上次更新是 2022 年 8 月 24 日,而 AngleSharp 是 2023 年 2 月,並且 AngleSharp 在 Github 上比較活躍,版本上也支援到 .NET 6 ,且屬於 .NET 基金會(.NET Foundation),故筆者選擇 AngleSharp,或許有機會再來試試看 HtmlAgilityPack
這個網站就是在蒐集歷史檔案,今天的範例就是使用 AngleSharp 套件將所有 Gif 檔案下載下來
上面是取回所有圖片連結,下載的部分則是使用 HttpClient:
註: """ 為 C# 11 語法,名稱為: 原始字串常值
爬取程式碼:
範例輸出:
參考資料:
Github - AngleSharp
AngleSharp Documentation
簡易比較如下:
套件 | AngleSharp 1.0.1 | HtmlAgilityPack 1.11.46 |
---|---|---|
.NET 支援 | .NET 6.0、.NET Standard 2.0、.NET Framework 4.6.1 | .NET Standard 1.3、.NET Framework 3.5 |
總下載量 | 60.5M | 107.1M |
目前版本下載量 | 157.4K | 2.9M |
平均每天下載量 | 16.9K | 24.1K |
Fork 數量 | 530 | 352 |
Stars 數量 | 4.6K | 2.3K |
雖然 HtmlAgilityPack 下載量比較多,但上次更新是 2022 年 8 月 24 日,而 AngleSharp 是 2023 年 2 月,並且 AngleSharp 在 Github 上比較活躍,版本上也支援到 .NET 6 ,且屬於 .NET 基金會(.NET Foundation),故筆者選擇 AngleSharp,或許有機會再來試試看 HtmlAgilityPack
安裝
先使用 NuGet 安裝 AngleSharp 套件,或是使用 .NET CLI 執行以下指令安裝
dotnet add package AngleSharp
基本使用
筆者在逛 Hacker News 時發現了一個很有趣的網站: Please be patient - This Page is Under Construction!這個網站就是在蒐集歷史檔案,今天的範例就是使用 AngleSharp 套件將所有 Gif 檔案下載下來
// 建立瀏覽器物件
var context = BrowsingContext.New(Configuration.Default.WithDefaultLoader());
// 目標連結:
string url = "http://textfiles.com/underconstruction/";
// 取得目標網頁的 HTML 內容
var document = await context.OpenAsync(url);
// 解析 HTML
var parser = new HtmlParser();
var html = parser.ParseDocument(document.ToHtml());
// 取得所有圖片連結
var images = html.Images.Select(l => l.GetAttribute("src")).ToList();
// 將圖片轉換為絕對路徑 url
var imageUrls = images.Select(image => new Uri(new Uri(url), image).AbsoluteUri).ToList();
上面是取回所有圖片連結,下載的部分則是使用 HttpClient:
// 檔案路徑
var path = @"C:\Users\ruyut\Desktop\images";
using var httpClient = new HttpClient();
// 下載所有檔案
foreach (var link in imageUrls)
{
// 取得檔案名稱
var fileName = Path.GetFileName(link);
// 建立要下載的檔案路徑
var filePath = Path.Combine(path, fileName);
// 下載檔案
var response = await httpClient.GetAsync(link);
// 將檔案儲存到指定路徑
using var fileStream = new FileStream(filePath, FileMode.Create);
await response.Content.CopyToAsync(fileStream);
Console.WriteLine($"Downloaded: {link}");
}
使用預存 HTML
測試時可以先擷取部分 html ,再使用下列方式讀取,就可以避免測試時一直呼叫實際連結
string html = """
<table>
<tr id="35258877">
</tr>
</table>
""";
var parser = new HtmlParser();
var document = parser.ParseDocument(html);
註: """ 為 C# 11 語法,名稱為: 原始字串常值
爬取資料範例
該如何定位元素呢? 就是使用 CSS 選擇器(也可以安裝套件後使用 XPath)來取得指定網頁元素,下面是爬取 Hacker News 網站的範例: 網頁內容節錄:
<tr id="35258877">
<td class="title"><span class="rank">1.</span></td>
<td class="votelinks" >
<a id="up_35258877" href="vote?id=35258877&how=up&goto=news">
<div class="votearrow" title="upvote"></div>
</a>
</td>
<td class="title">
<span class="titleline">
<a href="https://amturing.acm.org/?2023">ACM Turing Award honors Bob Metcalfe for Ethernet</a>
<span class="sitebit comhead"> (acm.org)
</span>
</span>
</td>
</tr>
<tr>
<td colspan="2"></td>
<td class="subtext">
<span class="subline">
378 points by robbiet480 4 hours ago | hide | 102 comments
</span>
</td>
</tr>
爬取程式碼:
var context = BrowsingContext.New(Configuration.Default.WithDefaultLoader());
// 目標連結:
string url = "https://news.ycombinator.com/";
// 取得目標網頁的 HTML 內容
var document = await context.OpenAsync(url);
// 選擇所有包含 id 屬性的 tr 元素
var trElements = document.QuerySelectorAll("tr[id]");
// 遍歷每個 tr 元素,並抽取 id、rank 和 title 屬性
foreach (var tr in trElements)
{
var id = tr.GetAttribute("id");
var rank = tr.QuerySelector(".title > .rank")?.TextContent;
var title = tr.QuerySelector(".titleline")?.TextContent;
// 文章連結
var link = tr.QuerySelector(".titleline > a[href]")?.GetAttribute("href");
// 標題下方的資訊
var data = tr.NextElementSibling?.QuerySelector(".subline")?.TextContent.Trim();
Console.WriteLine($"Id: {id} Rank: {rank} Title: {title}, Link: {link}, Data: {data}");
}
範例輸出:
Id: 35261065 Rank: 1. Title: GitHub Copilot X: The AI-powered developer experience (github.blog), Link: https://github.blog/2023-03-22-github-copilot-x-the-ai-powered-developer-experience/, Data: 186 points by todsacerdoti 49 minutes ago | hide | 110?comments
Id: 35258877 Rank: 2. Title: ACM Turing Award honors Bob Metcalfe for Ethernet (acm.org), Link: https://amturing.acm.org/?2023, Data: 398 points by robbiet480 4 hours ago | hide | 110?comments
Id: 35260401 Rank: 3. Title: The Simplicity of Single-File Golang Deployments (amazingcto.com), Link: https://www.amazingcto.com/simplicity-of-golang-systemd-deployments/, Data: 47 points by KingOfCoders 1 hour ago | hide | 40?comments
Id: 35258553 Rank: 4. Title: Show HN: ChatLLaMA – A ChatGPT style chatbot for Facebook's LLaMA (baseten.co), Link: https://chatllama.baseten.co/, Data: 213 points by aaronrelph 5 hours ago | hide | 110?comments
Id: 35260815 Rank: 5. Title: Launch HN: Flower (YC W23) – Train AI models on distributed or sensitive data, Link: item?id=35260815, Data: 17 points by niclane7 1 hour ago | hide | 8?comments
參考資料:
Github - AngleSharp
AngleSharp Documentation
留言
張貼留言
如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com