一隻可以抓取指定網頁中資料的程式,我們習慣稱呼為爬蟲程式。聽過很多人講爬蟲程式都是使用python來撰寫。不過既然小弟現在主要已寫C#為主,當然要寫一隻運行在.NET的C#爬蟲程式。
現在微軟的.NET Core已經可以正式的運行在Linux平台上,我想寫個爬蟲希望可以同值時運行在Windows平台與Linux平台上的話,當然選擇使用.net Core而不是.net Framework。
我們用瀏覽器在點擊一個連結、或是打開一個網頁時,輸入的http://
或https://
開頭的網址,都會發送Http請求到對應的網頁伺服器中,對方的網頁伺服器就回傳訊息給我們,其中Content欄位就是該網頁的HTML格式資料,瀏覽器解析HTML格式資料後我們便可以在瀏覽器上瀏覽這個網頁。
所以在爬蟲程式中,我們要模擬瀏覽器行為發送一個Http請求來取得網頁資料,再來就是使用AngleSharp這個套件來尋找Html的DOM元素來取得特定內容。
內容目錄
關於在.NET中發送Http請求
在.NET裡面可以使用WebClient 、HttpWebRequest、HttpClient這三種類別來發送Http請求到遠端伺服器去取得資料。其中,HttpClient是.NET Framework 4.5開始加入的類別,也是NET Core中官方建議使用的類別。
我們不建議您使用 WebClient 類別來進行新的開發。 請改用 System.Net.Http.HttpClient 類別。.NET Docs:NET Core 3.1 關於 WebClient 類別
我們不建議您使用 HttpWebRequest 進行新的開發。 請改用 System.Net.Http.HttpClient 類別。.NET Docs:NET Core 3.1 關於 HttpWebRequest 類別
(雖然寫不建議,不過.NET Core 3.1裡面還是有提供這兩個類別。)
延伸閱讀:HttpClient,該 using 還是 static?
建立專案
這邊我們使用命令列來建立一個新的.NET Core console專案,並命名為Console1
dotnet new console -n Console1
使用HttpClicent取得網頁資料
我們就依照官方的建議,使用HttpClient來取的網頁資料。(關於async Task Main()與await請看註一)
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
HttpClient httpClient = new HttpClient();
string url = "https://dannyliu.me";
var responseMessage = await httpClient.GetAsync(url); //發送請求
//檢查回應的伺服器狀態StatusCode是否是200 OK
if (responseMessage.StatusCode == System.Net.HttpStatusCode.OK)
{
string responseResult = responseMessage.Content.ReadAsStringAsync().Result;//取得內容
Console.WriteLine(responseResult);
}
Console.ReadKey();
}
}
}
安裝AngleSharp套件
在命令列中使用dotnet add package
來將AngleSharp套件加入到我們的專案
dotnet add package AngleSharp
使用AngleSharp
我們使用AngleSharp來幫我們抓HTML內的元素,會使用這一款套件的原因是因為內建了QuerySelector,使用方式跟JavaSript裡的document.QuerySelector一樣
using AngleSharp;
使用AngleSharp時的前置設定
var config = Configuration.Default;
var context = BrowsingContext.New(config);
傳入response資料
將我們用httpclient拿到的資料放入res.Content中()
//將我們用httpclient拿到的資料放入res.Content中()
var document = await context.OpenAsync(res=>res.Content(responseResult));
使用QuerySelector來取得內容
//QuerySelector("head")找出<head></head>元素
var head = document.QuerySelector("head");
Console.WriteLine(head.ToHtml());
//QuerySelector(".entry-content")找出class="entry-content"的所有元素
var contents = document.QuerySelectorAll(".entry-content");
foreach(var c in contents)
{
//取得每個元素的TextContent
Console.WriteLine(c.TextContent);
}
在GitHub看示範程式
補充:不用HttpClient,直接使用AngleSharp取得資料
//要抓取網頁資料需要WithDefaultLoader;
var config = Configuration.Default.WithDefaultLoader();
var context = BrowsingContext.New(config);
var document = await context.OpenAsync("https://dannyliu.me");
註一
如果要使用的話 async Task Main搭配await的話至少需要C#7.1以上,所以需要在專案設定檔中設定使用最新的C#版本。
例如在專案的csproj檔中加入<LangVersion>latest</LangVersion>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>