目录
1. 安装HtmlAgilityPack和HttpClient
随着互联网的发展,反爬虫技术也越来越成熟,很多网站都对爬取行为进行限制,例如限制访问频率、封禁IP等。为了规避这些限制,爬虫程序可以使用代理IP进行爬取。本文将介绍如何使用C#实现代理IP的爬取,并且解决一些常见的问题。
代理IP是一种用于隐藏真实IP地址的网络技术。通过使用代理服务器,我们可以将请求发送到代理服务器上,再由代理服务器代为发送请求,从而隐藏真实IP地址。代理服务器充当了客户端与目标服务器之间的中间人。在爬虫中,我们可以通过使用代理IP来规避目标网站的反爬虫策略。
免费代理IP网站是最常见的一种获取代理IP的方法。这些网站通常会提供公开的代理IP地址供开发者使用。通过爬取这些网站的代理IP列表,我们可以获取大量的代理IP地址。
除了免费代理IP网站外,还有一些第三方提供的代理IP API,比如站大爷代理ip、蝶鸟ip等。这些API通常需要付费使用,但提供的代理IP质量更高、稳定性更好。
使用C#实现代理IP爬取可以借助HtmlAgilityPack和HttpClient两个库。
使用NuGet包管理器,通过搜索"HtmlAgilityPack"和"HttpClient",安装这两个库。
以下代码实现了从免费代理IP网站获取代理IP的功能:
using System;
using System.Net.Http;
using HtmlAgilityPack;
class Program
{
? ? static async Task Main(string[] args)
? ? {
? ? ? ? var httpClient = new HttpClient();
? ? ? ? var html = await httpClient.GetStringAsync("https://www.freeip.top/?page=1");
? ? ? ? var htmlDocument = new HtmlDocument();
? ? ? ? htmlDocument.LoadHtml(html);
? ? ? ? var ipNodes = htmlDocument.DocumentNode.SelectNodes("//tbody/tr/td[1]");
? ? ? ? var portNodes = htmlDocument.DocumentNode.SelectNodes("//tbody/tr/td[2]");
? ? ? ? foreach (var ipNode in ipNodes)
? ? ? ? {
? ? ? ? ? ? Console.WriteLine(ipNode.InnerText);
? ? ? ? }
? ? ? ? foreach (var portNode in portNodes)
? ? ? ? {
? ? ? ? ? ? Console.WriteLine(portNode.InnerText);
? ? ? ? }
? ? }
}
以上代码使用HttpClient库发送GET请求获取代理IP网站的HTML代码,然后使用HtmlAgilityPack库将HTML代码解析成DOM树,然后通过XPath选择器提取出IP地址和端口号。
获取到代理IP后,我们可以使用HttpClient库进行访问目标网站。以下代码演示了如何使用代理IP发送GET请求:
static async Task Main(string[] args)
{
? ? var httpClientHandler = new HttpClientHandler()
? ? {
? ? ? ? UseProxy = true,
? ? ? ? Proxy = new WebProxy("127.0.0.1", 8888) // 代理IP地址和端口号
? ? };
? ? var httpClient = new HttpClient(httpClientHandler);
? ? var html = await httpClient.GetStringAsync("https://www.example.com");
? ? Console.WriteLine(html);
}
以上代码创建了一个HttpClientHandler对象,设置了代理IP地址和端口号,然后将该对象传递给HttpClient对象。接下来,使用HttpClient对象发送GET请求获取目标网站的内容。
免费代理IP网站提供的代理IP质量参差不齐,有些代理IP可能已经失效。为了保证代理IP的可用性,我们可以使用多线程进行代理IP的检测。以下代码演示了如何使用多线程进行代理IP的检测:
static async Task Main(string[] args)
{
? ? var httpClient = new HttpClient();
? ? var html = await httpClient.GetStringAsync("https://www.zdaye.com");
? ? var htmlDocument = new HtmlDocument();
? ? htmlDocument.LoadHtml(html);
? ? var ipNodes = htmlDocument.DocumentNode.SelectNodes("//tbody/tr/td[1]");
? ? var portNodes = htmlDocument.DocumentNode.SelectNodes("//tbody/tr/td[2]");
? ? List<Task<bool>> tasks = new List<Task<bool>>();
? ? foreach (var ipNode in ipNodes)
? ? {
? ? ? ? var ip = ipNode.InnerText;
? ? ? ? var port = portNodes[ipNodes.IndexOf(ipNode)].InnerText;
? ? ? ? tasks.Add(IsProxyIpValid(httpClient, ip, port));
? ? }
? ? await Task.WhenAll(tasks);
? ? foreach (var task in tasks)
? ? {
? ? ? ? if (task.Result)
? ? ? ? {
? ? ? ? ? ? Console.WriteLine("该代理IP可用");
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? Console.WriteLine("该代理IP不可用");
? ? ? ? }
? ? }
}
static async Task<bool> IsProxyIpValid(HttpClient httpClient, string ip, string port)
{
? ? try
? ? {
? ? ? ? var httpClientHandler = new HttpClientHandler()
? ? ? ? {
? ? ? ? ? ? UseProxy = true,
? ? ? ? ? ? Proxy = new WebProxy(ip, int.Parse(port))
? ? ? ? };
? ? ? ? var httpClient = new HttpClient(httpClientHandler);
? ? ? ? var response = await httpClient.GetAsync("https://www.example.com");
? ? ? ? return response.StatusCode == HttpStatusCode.OK;
? ? }
? ? catch
? ? {
? ? ? ? return false;
? ? }
}
以上代码使用多线程检测代理IP的可用性,通过向目标网站发起请求,判断响应的状态码是否为200来判断代理IP的有效性。
有些网站可能对单个IP地址的请求频率进行限制,因此我们可以使用多个代理IP轮流使用,从而规避频率限制。以下代码演示了如何在爬虫程序中轮流使用代理IP:
static async Task Main(string[] args)
{
? ? var httpClient = new HttpClient();
? ? var proxyIps = new List<string>() { "127.0.0.1:8888", "127.0.0.1:8889", "127.0.0.1:8890" };
? ? var currentProxyIpIndex = 0;
? ? // 循环使用代理IP发送请求
? ? for (int i = 0; i < 10; i++)
? ? {
? ? ? ? var currentProxyIp = proxyIps[currentProxyIpIndex];
? ? ? ? var proxyIp = currentProxyIp.Split(':')[0];
? ? ? ? var proxyPort = currentProxyIp.Split(':')[1];
? ? ? ? var httpClientHandler = new HttpClientHandler()
? ? ? ? {
? ? ? ? ? ? UseProxy = true,
? ? ? ? ? ? Proxy = new WebProxy(proxyIp, int.Parse(proxyPort))
? ? ? ? };
? ? ? ? var httpClient = new HttpClient(httpClientHandler);
? ? ? ? var html = await httpClient.GetStringAsync("https://www.example.com");
? ? ? ? Console.WriteLine(html);
? ? ? ? currentProxyIpIndex = (currentProxyIpIndex + 1) % proxyIps.Count;
? ? }
}
以上代码使用循环和取模运算符实现了轮流使用代理IP的功能。每次发送请求时,选择下一个代理IP发送请求。这样可以保证每个请求都使用不同的代理IP,提高爬取的效率。
本文介绍了使用C#实现代理IP爬取的方法,并解决了一些常见的问题。在实际的爬虫开发中,代理IP是一个非常有用的工具,可以帮助我们规避反爬虫策略,提高爬取效率。然而,需要注意的是,使用代理IP爬取也可能面临一些挑战,比如代理IP的可用性和频繁更换代理IP等问题,需要我们灵活应对。希望本文对大家理解代理IP爬取有所帮助。