返回博客
指南
苏丘·丹2023年4月13日阅读时间 8 分钟

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

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

什么是代理?

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

一旦目标服务器做出响应,代理服务器就会将响应发回给客户端。在网页抓取过程中,使用代理服务器可以隐藏抓取工具的 IP 地址,从而防止网站检测并拦截该请求。

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

创建一个 C# 项目

本文将使用 Windows 版的 Visual Studio 2022 和 .NET 6.0。如需跟随操作,请打开 Visual

Visual Studio“创建新项目”对话框已筛选为 C# 模板

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

在下一屏幕上选择项目的安装位置。然后,单击“下一步”进入“附加信息”屏幕。在单击“创建”之前,请确保已选中 .NET 7.0。

Visual Studio 的“配置新项目”对话框,其中显示了 C# 控制台应用程序的项目名称和位置字段

创建项目后,您将在屏幕上看到“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 的实例。修改后的客户端代码应如下所示:

使用 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 演示平台,并在“代码示例”部分中选择“代理模式”选项卡。

WebScrapingAPI 代码示例面板,展示了一个带有“复制”按钮的 curl 代理请求示例

现在,我们将把“代理模式”选项卡中生成的代理 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在无需任何基础设施开销的情况下,以企业级规模提取网页数据。