C#攻克反爬虫之代理IP爬取

目录

前言

一、什么是代理IP

二、代理IP的获取

1. 免费代理IP网站

2. 第三方API

三、C#实现代理IP爬取

1. 安装HtmlAgilityPack和HttpClient

2. 获取代理IP

3. 使用代理IP发送请求

四、常见问题及解决方案

1. 代理IP的可用性

2. 频繁更换代理IP

总结



前言

随着互联网的发展,反爬虫技术也越来越成熟,很多网站都对爬取行为进行限制,例如限制访问频率、封禁IP等。为了规避这些限制,爬虫程序可以使用代理IP进行爬取。本文将介绍如何使用C#实现代理IP的爬取,并且解决一些常见的问题。

一、什么是代理IP

代理IP是一种用于隐藏真实IP地址的网络技术。通过使用代理服务器,我们可以将请求发送到代理服务器上,再由代理服务器代为发送请求,从而隐藏真实IP地址。代理服务器充当了客户端与目标服务器之间的中间人。在爬虫中,我们可以通过使用代理IP来规避目标网站的反爬虫策略。

二、代理IP的获取

1. 免费代理IP网站

免费代理IP网站是最常见的一种获取代理IP的方法。这些网站通常会提供公开的代理IP地址供开发者使用。通过爬取这些网站的代理IP列表,我们可以获取大量的代理IP地址。

2. 第三方API

除了免费代理IP网站外,还有一些第三方提供的代理IP API,比如站大爷代理ip、蝶鸟ip等。这些API通常需要付费使用,但提供的代理IP质量更高、稳定性更好。

三、C#实现代理IP爬取

使用C#实现代理IP爬取可以借助HtmlAgilityPack和HttpClient两个库。

1. 安装HtmlAgilityPack和HttpClient

使用NuGet包管理器,通过搜索"HtmlAgilityPack"和"HttpClient",安装这两个库。

2. 获取代理IP

以下代码实现了从免费代理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地址和端口号。

3. 使用代理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请求获取目标网站的内容。

四、常见问题及解决方案

1. 代理IP的可用性

免费代理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的有效性。

2. 频繁更换代理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爬取有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/261841.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

坚持提升这个能力,让你越来越强大

哈喽&#xff0c;你好啊&#xff01;我是雷工。 今天在读《张一鸣管理日志》时&#xff0c;看到这么一句话&#xff1a; “产品创新要从根本上解决问题&#xff0c;而不是想办法绕过问题&#xff0c;解决的问题很可能就是将来的核心竞争力。” 这让我想起了亚马逊公司&#x…

还在用QQ拼音输入法吗?赶快卸载吧~!

最近总觉得我的C盘在莫名其妙的减少。之前的电脑C盘只有240G&#xff0c;所以我很在意C盘空间。但是&#xff0c;我发现买了新电脑&#xff0c;C盘空间也在莫名其妙减少。 随挨个文件夹检查。最后发现&#xff0c;QQ拼音的 dict 文件夹很大&#xff0c;居然有 30G多G。 30多~…

图片曝光修正方法(直方图均衡和CNN)

图像过曝或曝光不足时需要曝光处理&#xff0c; 这里以曝光不足举例。 直方图均衡法&#xff1a; 通过RGB通道的直方图均衡达到处理曝光不足的效果。 代码&#xff1a; underexpose cv2.imread("exposure_test.jpg") #underexpose cv2.cvtColor(underexpose, cv2…

leetcode 1314. 矩阵区域和(优质解法)

代码&#xff1a; class Solution {public int[][] matrixBlockSum(int[][] mat, int k) {int mmat.length;int nmat[0].length;int[][]answernew int[m][n]; //要返回的结果矩阵int[][]sumnew int[m1][n1]; //前缀和数组//初始化前缀和数组for(int i1;i<m;i){for(int…

Java泛型-13

泛型的好处 public class Demo01 {public static void main(String[] args) {Person<String> person new Person<String>("韩曙平");} }class Person<E>{ //创建时才定义数据类型 编译时就可以进行约束E str;public Person(E str){this.str str…

Github项目推荐:在线rename

项目地址 GitHub - JasonGrass/rename: 在线文件批量重命名 项目简介 一个开源的在线重命名文件工具。利用了新的浏览器API获取文件句柄&#xff0c;在不上传文件的情况下对文件进行重命名。可以作为前端文件操作api学习范例。 项目截图

PropTypes 在 React 中的使用心得

在 React 开发中&#xff0c;PropTypes 是一个非常有用的库&#xff0c;用于对组件的属性进行类型检查。它可以帮助我们在开发过程中捕获潜在的错误&#xff0c;提高代码的可靠性和可维护性。本文将介绍 PropTypes 的基本用法和一些使用心得。 一、什么是 PropTypes PropTypes…

Android 权限申请

在Android中&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用在运行时需要动态申请权限。以下是一些步骤来动态申请权限&#xff1a; 在应用的清单文件&#xff08;AndroidManifest.xml&#xff09;中声明需要的权限。例如&#xff0c;如果应…

Elasticsearch:生成 AI 中的微调与 RAG

在自然语言处理 (NLP) 领域&#xff0c;出现了两种卓越的技术&#xff0c;每种技术都有其独特的功能&#xff1a;微调大型语言模型 (LLM) 和 RAG&#xff08;检索增强生成&#xff09;。 这些方法极大地影响了我们利用语言模型的方式&#xff0c;使它们更加通用和有效。 在本文…

【制作系统盘】老毛桃装机,软碟通装机,硬盘装机---超详细讲解

目录 一 老毛桃装机 1.1 老毛桃是什么 1.2 下载安装 1.3 制作启动U盘 1.4 下载镜像文件 1.5 重装系统(PE安装) 1.6 开始重装系统 二 软碟通装机 2.1 软碟机概念 2.2 安装 2.3 ultraiso制作启动u盘 2.4 安装Win10系统 三 硬件装机 3.1 OneKeyGhost是什么 3.2 下…

DC-磁盘配额

2023年全国网络系统管理赛项真题 模块B-Windows解析 题目 在DC2驱动器C:\上设置磁盘配额&#xff0c;限制磁盘空间为5G&#xff0c;警告等级为3G&#xff0c;超出配额限制时记录事件&#xff0c;超出警告等级时记录事件。 配置步骤 验证 查看DC2驱动器C:\的磁盘配额&#xf…

【ECharts】雷达图

let chart echarts.init(this.$refs.radar_chart); let option {title: {text: 关键过程指标,},grid: {left: 0,},legend: {data: [个人, 小组, 团队],bottom: 0,itemWidth: 6,itemHeight: 6,},radar: {// shape: circle,indicator: [{ name: 成交额, max: 30000 },{ name: 成…

【MYSQL】-数据类型

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

分享一个项目——Sambert UI 声音克隆

文章目录 前言一、运行ipynb二、数据标注三、训练四、生成总结 前言 原教程视频 项目链接 运行一个ipynb&#xff0c;就可操作 总共四步 1&#xff09;运行ipynb 2&#xff09;数据标注 3&#xff09;训练 4&#xff09;生成 一、运行ipynb 等运行完毕后&#xff0c;获得该…

智能优化算法应用:基于饥饿游戏算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于饥饿游戏算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于饥饿游戏算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.饥饿游戏算法4.实验参数设定5.算法结果6.…

深度学习14—注意力机制与自注意力机制

注&#xff1a;以下均为个人学习笔记&#xff0c;发布只为方便学习阅读&#xff0c;若觉侵权&#xff0c;请联系删除&#xff01;&#xff01; 1.李沐老师课堂学习理解笔记 1.1 随意线索和不随意线索 1.2 注意力机制 通过注意力池化层来有偏向性的选择某些输入。 1.3 注意力…

vue打包内存问题解决办法<--- Last few GCs ---><--- JS stacktrace --->

**<— Last few GCs —> [18484:0000026763669610] 106760 ms: Mark-sweep 4016.0 <— JS stacktrace —> FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory** 解决办法&#xff1a; set NODE_OPTION…

Leetcode—77.组合【中等】

2023每日刷题&#xff08;六十五&#xff09; Leetcode—77.组合 算法思想 实现代码 class Solution { public:vector<vector<int>> combine(int n, int k) {vector<vector<int>> ans;vector<int> path;function<void(int)> dfs [&…

ansible的脚本-----playbook剧本

ansible的脚本-----playbook剧本 playbook组成部分&#xff1a; 1、tasks任务&#xff1a;包含要在目标主机上执行的操作&#xff0c;使用模块定义这些操作。每个任务都是一个模块的调用 2、variables变量&#xff1a;存储和传递数据&#xff0c;变量可以自定义&#xff0c;…

C++ STL——栈和队列(stack queue)

本节目标 1.stack的介绍和使用及其模拟实现 2.queue的介绍和使用及其模拟实现 3.priority_queue的介绍和使用及其模拟实现 4.容器适配器 1.stack的介绍和使用及其模拟实现 1.1 stack的介绍 stack的文档介绍 根据stack的文档介绍可以知道&#xff0c;stack是一种容器适配器…