C# 实现IP代理池调度

前言:稍微介绍下这个代码的用途,在做某些功能的时候,我们可能会用到IP代理,购买IP的时候也是可以选择长期高质量IP或者短失效但量大的IP,这个主要根据用途来购买;这里就是基于大量短失效IP做的一个IP调度,尽可能保证IP能够物尽其用。.

  1. 首先定义一个IPPool类,然后在构造函数中传入以下参数

    public class IPPool {     readonly string _ipUrl, _checkUrl;     readonly int _saveCount;     readonly bool _loopUse;     public ConcurrentQueue<string> IPQueue = new ConcurrentQueue<string>();     /// <summary>     /// 代理IP池     /// </summary>     /// <param name="ipUrl">代理IP的获取网址</param>     /// <param name="checkUrl">检查IP可用性的网址</param>     /// <param name="saveCount">IP池的存储量</param>     /// <param name="loopUse">是否循环使用</param>     public IPPool(string ipUrl, string checkUrl, int saveCount, bool loopUse=true)        {            _ipUrl = ipUrl;            _checkUrl = checkUrl;            _saveCount = saveCount;            _loopUse = loopUse;        }
  2. 解析网页上的IP地址,这里使用虚方法,以方便可以重写解析方法,应对不同的数据类型

     /// <summary>        /// 解析网址IP        /// </summary>        /// <returns></returns>        protected virtual List<string> Parse()        {            List<string> list = new List<string>();            try            {                HttpClient httpClient = new HttpClient();                httpClient.Timeout = new TimeSpan(0, 0, 10);                var result = httpClient.GetStringAsync(_ipUrl).Result;                JObject jobj = JObject.Parse(result);                if (jobj["code"].ToString() == "1")                {                    JArray jarr = (JArray)jobj["data"];                    foreach (var item in jarr)                    {                        string ip = item["ip"].ToString() + ":" + item["port"].ToString();                        list.Add(ip);                    }                }            }            catch { }            return list;        }
  3. 检查IP可用性,这里可以使用你需要访问的网址或者百度进行Get,保证可以访问到即可,同样使用虚方法定义

    /// <summary>        /// 检查IP可用性        /// </summary>        /// <param name="ip"></param>        /// <returns></returns>        protected virtual bool Check(string ip)        {            HttpClient httpClient = new HttpClient();            httpClient.Timeout = new TimeSpan(0, 0, 10);            bool result = httpClient.GetAsync(_checkUrl).Result.StatusCode == HttpStatusCode.OK;            return result;        }
    
  4. 开始获取,使用定时器获取,同样因为有设置队列的最大值,所以只有当低于这个阈值时才会进行补充,防止IP浪费的同时保证IP充足够用

    /// <summary>        /// 开始获取        /// </summary>        /// <param name="interval">获取间隔</param>        public virtual void Start(double interval)        {            System.Timers.Timer timer = new System.Timers.Timer(interval);            timer.Elapsed += (s, e) =>            {                if (IPQueue.Count < _saveCount)                {                    List<string> list = Parse();                    foreach (var ip in list)                    {                        IPQueue.Enqueue(ip);                    }                }            };            timer.Start();        }
  5. 获取IP,从队列中获取,如果设置了循环使用的话,不失效可以一直使用,进一步保证IP资源

/// <summary>        /// 获取IP        /// </summary>        /// <returns></returns>        public virtual string Get()        {            string ip = null;
            while (IPQueue.Count > 0)            {                IPQueue.TryPeek(out ip);                if (!string.IsNullOrEmpty(ip)&&Check(ip))                {                    if (!_loopUse)                    {                        IPQueue.TryDequeue(out ip);                    }                    break;                }                else                {                    IPQueue.TryDequeue(out string result);                }            }
            return ip;        }    }
  1. 为方便测试,我们自定义一个类继承IPPool,然后重写Parse以及Check方法

    public IPHelper(string ipUrl, string checkUrl, int saveCount, bool loopUse = true) : base(ipUrl, checkUrl, saveCount,loopUse)        {
            }        protected override List<string> Parse()        {            List<string> list = new List<string>();            list.Add(DateTime.Now.Ticks.ToString());            return list;        }        protected override bool Check(string ip)        {            return true;        }
  2. 最后调用下看看效果

    private async void button1_Click(object sender, EventArgs e)        {            listBox1.Items.Clear();            IPHelper iPHelper = new IPHelper("", "", 10,false);            iPHelper.Start(200);            for (int i = 0; i < 5; i++)            {                string ip = iPHelper.Get();                if (ip != null)                {                    listBox1.Items.Add(ip);                }                await Task.Delay(500);            }        }
            private async void button2_Click(object sender, EventArgs e)        {            listBox1.Items.Clear();            IPHelper iPHelper = new IPHelper("", "", 10);            iPHelper.Start(200);            for (int i = 0; i < 5; i++)            {                string ip = iPHelper.Get();                if (ip != null)                {                    listBox1.Items.Add(ip);                }                await Task.Delay(500);            }        }

实现效果:

C# 实现IP代理池调度