返回博客
指南
Suciu DanLast updated on Mar 31, 20262 min read

利用代理和 C# HttpClient 绕过限制并高效抓取数据

利用代理和 C# HttpClient 绕过限制并高效抓取数据

网络爬虫是一种强大的工具,可帮助您从网站中提取有价值的数据,以满足各种需求。然而,许多网站会阻止爬虫行为,以保护其数据。绕过这些限制的一种方法是使用代理服务器。

本文将探讨如何在 C# 中使用 HttpClient(一款用于发送 HTTP 请求的流行库)配合代理服务器。我们将涵盖使用前的准备工作、配置方法,以及调试和故障排除的技巧。

此外,我们将详细讲解如何发送请求以及如何优化请求性能。读完本文后,您将充分掌握如何在 C# HttpClient 中使用代理,并了解它如何为您的网页抓取工作带来帮助。

什么是代理?

代理(也称为代理服务器)在客户端(如网页浏览器或爬虫)与目标服务器(如网站)之间充当中间人。客户端向代理发送请求,代理再将其转发至目标服务器。

目标服务器响应后,代理会将响应结果发回给客户端。在网页抓取中,使用代理可以隐藏抓取工具的 IP 地址,防止网站检测并拦截请求。

使用多个代理服务器也有助于规避检测和封禁。部分代理服务商甚至提供IP轮换功能,为您的请求提供额外的防护,防止被封禁。

创建 C# 项目

本文将使用 Windows 版的 Visual Studio 2022 和 .Net 6.0。若要跟随操作,请打开 Visual

在 Visual Studio 中,从“所有语言”下拉菜单中选择 C#。如果未显示“控制台应用程序”模板,请使用“搜索模板”输入框进行查找。然后单击“下一步”。

在下一屏幕中选择项目位置。随后点击“下一步”进入“附加信息”屏幕。请确保已选中 .NET 7.0,再点击“创建”。

项目创建完成后,屏幕上将显示“Hello World”代码:

// See https://aka.ms/new-console-template for more information

Console.WriteLine("Hello, World!");

发送 HTTP 请求

让我们使用 `HttpClient` 发出第一个请求。将示例代码替换为以下内容:

using var client = new HttpClient();

var result = await client.GetStringAsync("https://api.ipify.org?format=json");

Console.WriteLine(result); 

此代码使用 System.Net.Http 命名空间中的 HttpClient 类,向 https://api.ipify.org/ 端点发送 HTTP GET 请求,并将响应作为字符串获取。

以下是代码解析:

  • `using var client = new HttpClient();`:此行代码创建 `HttpClient` 类的实例,并将其赋值给变量 client。`using` 语句确保在不再需要客户端对象时能正确释放它。
  • `var result = await client.GetStringAsync("https://api.ipify.org/");`:此行代码使用客户端对象的 `GetStringAsync()` 方法向 https://api.ipify.org/ 端点发送 GET 请求。该方法将响应读取为字符串,并将其存储在变量 result 中。 `await` 关键字使请求异步化,允许程序在请求处理期间继续执行其他代码。
  • `Console.WriteLine(result);`:此行将 `result` 变量的内容(即 GET 请求的响应)写入控制台。

保存代码并运行。您将在终端中看到您的 IP 地址。

使用 HttpClient 配合代理

在继续编写代码之前,请访问 Free Proxy List 网站并选择离您所在位置最近的代理。本示例中,我将选择一个位于德国的代理。请记下所选代理的 IP 地址和端口。

要在 HttpClient 中使用代理,我们需要创建一个 HttpClientHandler 实例。在此实例中,我们需要设置两个属性:代理 URL 和端口,以及 `ServerCertificateCustomValidationCallback`。虽然这个变量名很长,但它非常重要。

`ServerCertificateCustomValidationCallback` 指示 HttpClientHandler 忽略任何 HTTPS 证书错误。您可能想知道为什么要这样做。

代理服务器会在将流量转发至目标服务器之前,拦截并检查流量(包括 HTTPS 证书)。因此,目标服务器向代理服务器展示的证书可能与向客户端展示的证书不同。

默认情况下,HttpClient 及其他类似库会验证目标服务器提供的证书,若证书无效或与客户端收到的证书不匹配,则会抛出异常。这就是证书错误的来源。

在使用代理模式时忽略 HTTPS 证书错误,即使证书无效也能让请求继续进行,这在某些情况下非常有用,例如当证书被代理服务器拦截并修改时。

现在是时候编写代码了。让我们从 HttpClientHandler 实例开始:

using System.Net;

using var httpClientHandler = new HttpClientHandler

{

	Proxy = new WebProxy("http://5.9.139.204:24000"),

	ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator

};

我们需要向 HttpClient 类提供一个 HttpClientHandler 实例。修改后的客户端代码应如下所示:

using var client = new HttpClient(httpClientHandler);

完整的代码应如下所示:

using System.Net;

using var httpClientHandler = new HttpClientHandler

{

	Proxy = new WebProxy("http://5.9.139.204:24000"),

	ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator

};

using var client = new HttpClient(httpClientHandler);

var result = await client.GetStringAsync("https://api.ipify.org?format=json");

Console.WriteLine(result);

运行代码后,返回的将是代理 IP 地址而非您的 IP 地址。您可以在浏览器中打开 ipify 网址并对比结果。

进行身份验证

当您注册高级代理服务时,会收到一个用户名和密码,用于在应用程序中进行身份验证。

现在是时候用以下定义替换 WebProxy 定义了:

Proxy = new WebProxy

{

    	Address = new Uri($"http://5.9.139.204:24000"),

    	Credentials = new NetworkCredential(

        	userName: "PROXY_USERNAME",

        	password: "PROXY_PASSWORD"

    	)

},

通过替换占位符凭据、更新代理 URL 并执行代码,你会发现输出的 IP 地址与你的计算机所使用的 IP 地址不同。快来试试吧!

轮换代理

轮换代理非常有用,因为它有助于避免被检测,并防止网站封禁您的 IP 地址。网站可能会监控并封禁在短时间内发出过多请求的 IP 地址,或与数据抓取活动相关的 IP 地址。

我们可以利用 Free Proxy List 网站生成代理列表,并在每次发送请求时轮换使用。通过这种方式,每次请求都会使用不同的 IP 地址,从而降低目标网站对请求的可疑度。

请注意,您在该网站上找到的代理列表可能与我编写的列表有所不同。我挑选了五个代理,并像这样将其定义在一个列表中:

List<string> proxiesList = new List<string> {

	"http://65.108.230.238:45977",

	"http://163.116.177.46:808",

	"http://163.116.177.31:808",

	"http://20.111.54.16:80",

	"http://185.198.61.146:3128"

};

让我们从该列表中随机选择一个索引,并使用 Uri 类获取该索引对应的项:

var random = new Random();

int index = random.Next(proxiesList.Count);

现在我们需要将所有部分整合起来。您的爬虫代码最终版本应如下所示:

using System.Net;

List<string> proxiesList = new List<string> {

	"http://65.108.230.238:45977",

	"http://163.116.177.46:808",

	"http://163.116.177.31:808",

	"http://20.111.54.16:80",

	"http://185.198.61.146:3128"

};

var random = new Random();

int index = random.Next(proxiesList.Count);

using var httpClientHandler = new HttpClientHandler

{

	Proxy = new WebProxy(proxiesList[index]),

	ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator

};

using var client = new HttpClient(httpClientHandler);

var result = await client.GetStringAsync("https://api.ipify.org?format=json");

Console.WriteLine(result);

使用 WebScrapingAPI 代理

与免费代理相比,选择 WebScrapingAPI 等服务提供的付费代理是更优的选择,因为它们更可靠、速度更快且安全性更高。付费代理不易被网站封锁,响应时间也更短。

相比之下,免费代理可能速度慢、不稳定、含有恶意软件,且因目标网站会屏蔽您的请求,导致失败率更高。

有兴趣试用 WebScrapingAPI 吗?没问题,只需注册我们的 14 天免费试用。您可以使用 5,000 个积分测试所有可用功能。

注册账号后,请前往 API 沙盒,在“代码示例”部分选择“代理模式”选项卡。

现在,我们将把“代理模式”选项卡中生成的代理 URL 用于我们的 C# 实现。

请将 httpClientHandler 中的代理 URL 和凭据更新为如下所示:

using var httpClientHandler = new HttpClientHandler

{

	Proxy = new WebProxy

	{

    	Address = new Uri($"http://proxy.webscrapingapi.com:80"),

    	Credentials = new NetworkCredential(

        	userName: "webscrapingapi.render_js=0.device=desktop.proxy_type=datacenter",

        	password: "YOUR_API_KEY"

    	)

	},

	ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator

};

您可以通过username属性启用或禁用特定的API功能。请记得在password属性中设置您的API密钥。您可在此处查阅完整文档。

每次执行此代码时,您都会获得不同的 IP 地址,因为 WebScrapingAPI 会在每次请求时轮换 IP。您可通过阅读“代理模式”文档进一步了解此功能。

您还可以选择在数据中心代理和住宅代理之间切换。有关此功能的更多详细信息,请参阅文档中的“代理”部分

结论

使用代理是网络爬虫的关键环节,它能帮助您隐藏 IP 地址并访问受限网站。C# 中的 HttpClient 库是提取数据的强大工具,配合可靠的代理使用,可实现高效快速的数据提取。

订阅 WebScrapingAPI 这样的高级代理服务,您将能够使用包括 IP 轮换以及在数据中心代理和住宅代理之间切换在内的多种功能。

希望本文能帮助您深入了解如何在 HttpClient 中使用代理,以及它如何满足您的爬取需求。欢迎注册我们的 14 天免费试用,亲身体验我们的服务并探索所有功能。

关于作者
Suciu Dan, 联合创始人 @ WebScrapingAPI
Suciu Dan联合创始人

Suciu Dan 是 WebScrapingAPI 的联合创始人,他撰写了关于 Python 网页抓取、Ruby 网页抓取以及代理基础设施的实用指南,这些指南专为开发者而设计。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网络数据。