c# 如何实现一个简单的爬虫

来源:这里教程网 时间:2026-02-21 17:38:19 作者:

HttpClient
发起 GET 请求获取网页内容

直接用

HttpClient
是 C# 最轻量、最现代的做法,比已过时的
WebClient
更可靠,也比
HttpWebRequest
更简洁。注意必须复用同一个
HttpClient
实例,否则容易触发端口耗尽(
SocketException: Too many open files
)。

在类级别声明并复用:
private static readonly HttpClient client = new HttpClient();
设置超时避免卡死:
client.Timeout = TimeSpan.FromSeconds(10);
记得处理响应状态码:
if (!response.IsSuccessStatusCode)
,不要只靠异常判断
await response.Content.ReadAsStringAsync()
读取 HTML 字符串,不是
ReadAsByteArrayAsync
(除非你要解析二进制)

HtmlAgilityPack
解析 HTML 提取链接和文本

HtmlAgilityPack
是 .NET 生态里最稳定、兼容性最好的 HTML 解析库,能容忍 malformed HTML(比如缺少闭合标签),比正则匹配靠谱得多。它不依赖浏览器引擎,纯内存解析,速度快。

安装包:
dotnet add package HtmlAgilityPack
加载 HTML:
var doc = new HtmlDocument(); doc.LoadHtml(htmlString);
查所有链接:
doc.DocumentNode.SelectNodes("//a[@href]")
,注意 XPath 中属性要带
@
提取文本内容别用
InnerText
(含换行/空白多),优先用
InnerHtml
+
WebUtility.HtmlDecode()
清理

如何避免被目标网站封禁(基础反反爬)

多数小站点没严格风控,但加几条基础头就能绕过最简单的 UA 拦截。别学某些教程发一堆无意义请求头,反而显得可疑。

必设
User-Agent
:用主流浏览器值,比如
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
可选加
Accept
Accept-Language
,但不是必须;
Referer
只在需要模拟页面跳转时才设
加延时是关键:
await Task.Delay(1000)
(1 秒),别用
Thread.Sleep
阻塞线程
不要并发猛刷——单线程 + 延迟,比十个并发还安全
using System;
using System.Net.Http;
using System.Threading.Tasks;
using HtmlAgilityPack;
<p>class SimpleCrawler
{
private static readonly HttpClient client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};</p><pre class='brush:php;toolbar:false;'>static SimpleCrawler()
{
    client.DefaultRequestHeaders.UserAgent.ParseAdd(
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
}
public static async Task CrawlAsync(string url)
{
    try
    {
        var html = await client.GetStringAsync(url);
        var doc = new HtmlDocument();
        doc.LoadHtml(html);
        foreach (var link in doc.DocumentNode.SelectNodes("//a[@href]"))
        {
            var href = link.GetAttributeValue("href", "");
            if (Uri.IsWellFormedUriString(href, UriKind.Absolute))
                Console.WriteLine(href);
        }
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"Request failed: {ex.StatusCode}");
    }
}

}

真正难的不是发请求或提链接,而是判断哪些 URL 值得跟进、怎么去重、怎么处理跳转和相对路径、何时停——这些逻辑一加上,就不再是“简单”爬虫了。

相关推荐