温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

c#如何批量抓取免费代理并且验证有效性

发布时间:2021-07-26 10:58:50 来源:亿速云 阅读:137 作者:小新 栏目:编程语言

小编给大家分享一下c#如何批量抓取免费代理并且验证有效性,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

1.从哪些网页上可以抓取免费的代理IP?

百度一下“免费代理ip”挺多的。

2.代理IP稳定吗?有什么作用?

这种免费的代理ip时效性和有效性都不强,上面这三个免费的代理网站,时效性大概在十几秒到1个小时不等,一般需要自己处理验证后使用,提高命中率。可适用于隐藏网页IP(有些网站还不准使用代理ip,比如豆瓣,其实挺尴尬的,内容这么贵吗),一般常用于空间留言、刷网站流量、网赚任务、批量注册账号等,只要没有其他限制,需要频繁更换ip都可以使用。

3.ping通IP就是有效的吗?如何验证代理是否有效

好吧,这有点废话,进行端口测试才是最有效的,能ping通并不代表代理有效,不能平通也不一定代理不可用。可以使用HttpWebRequest,也可以使用Scoket,当然HttpWebRequest比Socket连接代理ip、port要慢。

4.一次提取多少代理合适?

代理ip时效性不强、并且有效性也不高,所以只能从一些代理ip的网站上批量定时去获取,有的代理在一分钟内使用是有限制的,所以说限制比较多。

5.http代理和https代理有什么区别?

需要访问https的网站就需要使用https代理了,比如百度,需要访问http的代理,可以使用http。这个并不是100%的。

检测代理ip有效性步骤如下:

1.使用HttpWebRequest、HttpWebResponse请求代理ip的网页,获取包含代理的网页内容

2.使用HtmlAgilityPack或者正则表达式对抓取的内容进行截取,保存到代理集合

3.拿到代理集合,多线程发起http请求,比如访问百度,是否成功,成功则存到Redis里面。

效果图如下:

c#如何批量抓取免费代理并且验证有效性

使用HttpWebRequest发起请求

Request.cs如下,主要就是两个方法,一个方法是验证代理ip是否有效,设置HttpWebRequest的Proxy属性,请求百度,看到有些文章大多数会获取响应的内容,如果内容符合请求的网址则证明代理哟有效,实际上根据HttpStatusCode 200就可以判断是否验证有效。

【注意】建的是控制台程序,使用了异步,所以还是建.net core吧,c#语言的版本7.1。C#如何在控制台程序中使用异步

public class Request  {  /// <summary>  /// 验证代理ip有效性  /// </summary>  /// <param name="proxyIp">代理IP</param>  /// <param name="proxyPort">代理IP 端口</param>  /// <param name="timeout">详情超时</param>  /// <param name="url">请求的地址</param>  /// <param name="success">成功的回调</param>  /// <param name="fail">失败的回调</param>  /// <returns></returns>  public static async System.Threading.Tasks.Task getAsync(string proxyIp,int proxyPort, int timeout,string url, Action success, Action<string> fail)  {   System.GC.Collect();   HttpWebRequest request = null;   HttpWebResponse response = null;   try   {   request = (HttpWebRequest)WebRequest.Create(url);   //HttpWebRequest request = HttpWebRequest.CreateHttp(url);   request.Timeout =timeout;   request.KeepAlive = false;   request.Proxy = new WebProxy(proxyIp,proxyPort);   response = await request.GetResponseAsync() as HttpWebResponse;   if (response.StatusCode == HttpStatusCode.OK)   {    success();   }   else   {    fail(response.StatusCode+":"+response.StatusDescription);   }   }   catch (Exception ex)   {   fail("请求异常"+ex.Message.ToString());   }   finally   {   if (request != null)   {    request.Abort();    request = null;   }   if (response != null)   {    response.Close();   }   }  }  /// <summary>  /// 发起http请求  /// </summary>  /// <param name="url"></param>  /// <param name="success">成功的回调</param>  /// <param name="fail">失败的回调</param>  public static void get(string url,Action<string> success,Action<string> fail)  {   StreamReader reader = null;   Stream stream = null;   WebRequest request = null;   HttpWebResponse response = null;   try   {   request = WebRequest.Create(url);   request.Timeout = 2000;   response = (HttpWebResponse)request.GetResponse();   if (response.StatusCode == HttpStatusCode.OK)   {    stream = response.GetResponseStream();    reader = new StreamReader(stream);    string result = reader.ReadToEnd();    success(result);   }   else   {    fail(response.StatusCode+":"+response.StatusDescription);   }   }   catch (Exception ex)   {   fail(ex.ToString());   }   finally   {   if (reader != null)    reader.Close();   if (stream != null)    stream.Close();   if(response!=null)    response.Close();   if(request!=null)    request.Abort();   }  }  }

抓取免费代理,并检查是否有效

ProxyIpHelper.cs 中主要有四个方法,检查ip是否可用CheckProxyIpAsync、抓取xicidaili.com的代理GetXicidailiProxy、抓取ip3366.net的代理GetIp3366Proxy、抓取66ip.cn的代理GetIp3366Proxy。如果想多抓取几个网站可以多写几个。

public class ProxyIpHelper  {   private static string address_xicidaili = "http://www.xicidaili.com/wn/{0}";   private static string address_66ip = "http://www.66ip.cn/nmtq.php?getnum=20&isp=0&anonymoustype=0&start=&ports=&export=&ipaddress=&area=1&proxytype=1&api=66ip";   private static string address_ip3366 = "http://www.ip3366.net/?stype=1&page={0}";   /// <summary>   /// 检查代理IP是否可用   /// </summary>   /// <param name="ipAddress">ip</param>   /// <param name="success">成功的回调</param>   /// <param name="fail">失败的回调</param>   /// <returns></returns>   public static async Task CheckProxyIpAsync(string ipAddress, Action success, Action<string> fail)   {    int index = ipAddress.IndexOf(":");    string proxyIp = ipAddress.Substring(0, index);    int proxyPort = int.Parse(ipAddress.Substring(index + 1));    await Request.getAsync(proxyIp, proxyPort, 3000, "https://www.baidu.com/", () =>    {     success();    }, (error) =>    {     fail(error);    });   }   /// <summary>   /// 从xicidaili.com网页上去获取代理IP,可以分页   /// </summary>   /// <param name="page"></param>   /// <returns></returns>   public static List<string> GetXicidailiProxy(int page)   {    List<string> list = new List<string>();    for (int p = 1; p <= page; p++)    {     string url = string.Format(address_xicidaili, p);     Request.get(url,(docText)=> {      if (!string.IsNullOrWhiteSpace(docText))      {       HtmlDocument doc = new HtmlDocument();       doc.LoadHtml(docText);       var trNodes = doc.DocumentNode.SelectNodes("//table[@id='ip_list']")[0].SelectNodes("./tr");       if (trNodes != null && trNodes.Count > 0)       {        for (int i = 1; i < trNodes.Count; i++)        {         var tds = trNodes[i].SelectNodes("./td");         string ipAddress = tds[1].InnerText + ":" + int.Parse(tds[2].InnerText); ;         list.Add(ipAddress);        }       }      }     },(error)=> {      Console.WriteLine(error);     });    }    return list;     }   /// <summary>   /// 从ip3366.net网页上去获取代理IP,可以分页   /// </summary>   /// <param name="page"></param>   /// <returns></returns>   public static List<string> GetIp3366Proxy(int page)   {    List<string> list = new List<string>();    for (int p = 1; p <= page; p++)    {     string url = string.Format(address_ip3366, p);     Request.get(url, (docText) => {      if (!string.IsNullOrWhiteSpace(docText))      {       HtmlDocument doc = new HtmlDocument();       doc.LoadHtml(docText);       var trNodes1 = doc.DocumentNode.SelectNodes("//table")[0];       var trNodes2 = doc.DocumentNode.SelectNodes("//table")[0].SelectSingleNode("//tbody");       var trNodes = doc.DocumentNode.SelectNodes("//table")[0].SelectSingleNode("//tbody").SelectNodes("./tr");       if (trNodes != null && trNodes.Count > 0)       {        for (int i = 1; i < trNodes.Count; i++)        {         var tds = trNodes[i].SelectNodes("./td");         if (tds[3].InnerHtml == "HTTPS")         {          string ipAddress = tds[0].InnerText + ":" + int.Parse(tds[1].InnerText); ;          list.Add(ipAddress);         }        }       }      }     }, (error) => {      Console.WriteLine(error);     });    }    return list;    }   /// <summary>   /// 从66ip.cn中去获取,不需要分页   /// </summary>   /// <returns></returns>   public static List<string> Get66ipProxy()   {    List<string> list = new List<string>();    Request.get(address_66ip,    (docText)=> {     int count = 0;     if (string.IsNullOrWhiteSpace(docText) == false)     {      string regex = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\:\\d{1,5}";      Match mstr = Regex.Match(docText, regex);      while (mstr.Success && count < 20)      {       string tempIp = mstr.Groups[0].Value;       list.Add(tempIp);       mstr = mstr.NextMatch();       count++;      }     }    },    (error)=> {     Console.WriteLine(error);    });    return list;   }  }

使用Timer定时抓取,并检查,成功则保存到redis

c#有三种定时器,这里定时器是使用System.Threading命名空间, 这个Timer会开启新的线程,抓取三个网页定义了三个Timer对象。每一次抓取都会保存上一次抓取的集合,检查前,会进行对比,取出新的集合也就是没有重复的那部分。有效性的ip比较低,这里没有做统计,如果代码再优化一下,可以做一下统计,看看程序的主入口吧,最终的实现如下:

class Program  {   static bool timer_ip3366_isCompleted = true;   static bool timer_xicidaili_isCompleted = true;   static bool timer_66ip_isCompleted = true;   static Timer timer_ip3366, timer_xicidaili, timer_66ip;   private static List<string> lastListip3366,lastList66ip,lastListxicidaili;//保存上一次抓取的代理,与下一次进行对比,取新的集合进行检查筛选   static async Task Main(string[] args)   {    System.Net.ServicePointManager.DefaultConnectionLimit = 2000;    Console.WriteLine("hellow proxyIp");    Console.ReadLine();    lastList66ip = new List<string>();    lastListip3366 = new List<string>();    lastListxicidaili = new List<string>();    timer_ip3366 = new Timer(async (state) =>    {     await TimerIp3366Async();    }, "processing timer_ip3366 event", 0,1000*30);    timer_xicidaili = new Timer(async (state) =>    {     await TimerXicidailiAsync();    }, "processing timer_xicidaili event", 0, 1000 * 60);    timer_66ip = new Timer(async (state) =>    {     await Timer66ipAsync();    }, "processing timer_66ip event", 0, 1000*30);        Console.ReadLine();   }   private static async Task Timer66ipAsync()   {    if (timer_66ip_isCompleted)    {     timer_66ip_isCompleted = false;     List<string> checkList = new List<string>();     var listProxyIp = ProxyIpHelper.Get66ipProxy();     if (listProxyIp.Count > 0)     {      Console.ForegroundColor = ConsoleColor.DarkCyan;      Console.WriteLine("66ip.cn 抓取到" + listProxyIp.Count + "条记录,正在对比.........");      listProxyIp.ForEach(f =>      {       if (!lastList66ip.Contains(f))       {        checkList.Add(f);       }      });      lastList66ip = listProxyIp;      if (checkList.Count > 0)      {       Console.ForegroundColor = ConsoleColor.DarkCyan;       Console.WriteLine("66ip.cn 需要检查" + checkList.Count + "条记录,正在进行检测是否有效..........");       for (int i = 0; i < checkList.Count; i++)       {        string ipAddress = checkList[i];        await ProxyIpHelper.CheckProxyIpAsync(ipAddress, () =>        {         bool insertSuccess = RedisHelper.InsertSet(ipAddress);         Console.ForegroundColor = ConsoleColor.White;         Console.WriteLine("66ip.cn");         if (insertSuccess)         {          Console.WriteLine("success" + ipAddress + "任务编号:" + i + "当前任务线程:" + Thread.CurrentThread.ManagedThreadId);         }         Console.WriteLine("重复插入" + ipAddress + "任务编号:" + i + "当前任务线程:" + Thread.CurrentThread.ManagedThreadId);        }, (error) =>        {         Console.ForegroundColor = ConsoleColor.Green;         Console.WriteLine("66ip.cn");         Console.WriteLine("error:" + ipAddress + error + "任务编号:" + i + "当前任务线程:" + Thread.CurrentThread.ManagedThreadId);        });       }       timer_66ip_isCompleted = true;       Console.ForegroundColor = ConsoleColor.DarkCyan;       Console.WriteLine("66ip.cn" + checkList.Count + "条记录,已经检测完成,正在进行下一次检查");      }      else      {       timer_66ip_isCompleted = true;       Console.ForegroundColor = ConsoleColor.DarkCyan;       Console.WriteLine("66ip.cn没有需要检查的代理ip");      }     }     else     {      timer_66ip_isCompleted = true;      Console.ForegroundColor = ConsoleColor.DarkCyan;      Console.WriteLine("66ip.cn没有获取到代理ip");     }    }   }   private static async Task TimerXicidailiAsync()   {    if (timer_xicidaili_isCompleted)    {     //取出需要检查的ip地址,第一次100条则checklist就是100条记录,     //第二次的100条中只有10是和上一次的不重复,则第二次只需要检查这10条记录     timer_xicidaili_isCompleted = false;     List<string> checkList = new List<string>();     var listProxyIp = ProxyIpHelper.GetXicidailiProxy(1);     if (listProxyIp.Count > 0)     {      Console.WriteLine("xicidaili.com 抓取到" + listProxyIp.Count + "条记录,正在对比............");      listProxyIp.ForEach(f =>      {       if (!lastListxicidaili.Contains(f))       {        checkList.Add(f);       }      });      lastListxicidaili = listProxyIp;      if (checkList.Count > 0)      {       Console.ForegroundColor = ConsoleColor.DarkCyan;       Console.WriteLine("xicidaili.com 需要检查" + checkList.Count + "条记录,正在进行检测是否有效..........");       for (int i = 0; i < checkList.Count; i++)       {        string ipAddress = checkList[i];        await ProxyIpHelper.CheckProxyIpAsync(ipAddress, () =>        {         bool insertSuccess = RedisHelper.InsertSet(ipAddress);         Console.ForegroundColor = ConsoleColor.White;         Console.WriteLine("xicidaili.com");         if (insertSuccess)         {          Console.WriteLine("success" + ipAddress + "任务编号:" + i + "当前任务线程:" + Thread.CurrentThread.ManagedThreadId);         }         else          Console.WriteLine("重复插入" + ipAddress + "任务编号:" + i + "当前任务线程:" + Thread.CurrentThread.ManagedThreadId);        }, (error) =>        {         Console.WriteLine("xicidaili.com");         Console.ForegroundColor = ConsoleColor.Red;         Console.WriteLine("error:" + ipAddress + error + "任务编号:" + i + "当前任务线程:" + Thread.CurrentThread.ManagedThreadId);        });       }       timer_xicidaili_isCompleted = true;       Console.ForegroundColor = ConsoleColor.DarkCyan;       Console.WriteLine("xicidaili.com" + checkList.Count + "条记录,已经检测完成,正在进行下一次检查");      }      else      {       timer_xicidaili_isCompleted = true;       Console.ForegroundColor = ConsoleColor.DarkCyan;       Console.WriteLine("xicidaili.com没有需要检查的代理ip");      }     }     else     {      timer_xicidaili_isCompleted = true;      Console.ForegroundColor = ConsoleColor.DarkCyan;      Console.WriteLine("xicidaili.com没有获取到代理ip");     }    }   }   private static async Task TimerIp3366Async()   {    if (timer_ip3366_isCompleted)    {     timer_ip3366_isCompleted = false;     List<string> checkList = new List<string>();     var listProxyIp = ProxyIpHelper.GetIp3366Proxy(4);     if (listProxyIp.Count > 0)     {      Console.ForegroundColor = ConsoleColor.DarkCyan;      Console.WriteLine("ip3366.net 抓取到" + listProxyIp.Count + "条记录,正在进行检测是否有效..........");      listProxyIp.ForEach(f =>      {       if (!lastListip3366.Contains(f))       {        checkList.Add(f);       }      });      lastListip3366 = listProxyIp;      if (checkList.Count != 0)      {       Console.ForegroundColor = ConsoleColor.DarkCyan;       Console.WriteLine("ip3366.net 需要检查" + checkList.Count + "条记录,正在进行检测是否有效..........");       for (int i = 0; i < checkList.Count; i++)       {        string ipAddress = checkList[i];        await ProxyIpHelper.CheckProxyIpAsync(ipAddress, () =>        {         bool insertSuccess = RedisHelper.InsertSet(ipAddress);         Console.ForegroundColor = ConsoleColor.White;         Console.WriteLine("ip3366.net");         if (insertSuccess)         {          Console.WriteLine("success" + ipAddress + "任务编号:" + i + "当前任务线程:" + Thread.CurrentThread.ManagedThreadId);         }         else         {          Console.ForegroundColor = ConsoleColor.Red;          Console.WriteLine("重复插入" + ipAddress + "任务编号:" + i + "当前任务线程:" + Thread.CurrentThread.ManagedThreadId);         }        }, (error) =>        {         Console.ForegroundColor = ConsoleColor.Yellow;         Console.WriteLine("ip3366.net");         Console.WriteLine("error " + ipAddress + "任务编号:" + i + "当前任务线程:" + Thread.CurrentThread.ManagedThreadId);        });       }       timer_ip3366_isCompleted = true;       Console.WriteLine("ip3366.net" + checkList.Count + "条记录,已经检测完成,正在进行下一次检查");      }      else      {       timer_ip3366_isCompleted = true;       Console.ForegroundColor = ConsoleColor.DarkCyan;       Console.WriteLine("ip3366.net没有需要检查的代理ip");      }     }     else     {      timer_ip3366_isCompleted = true;      Console.ForegroundColor = ConsoleColor.DarkCyan;      Console.WriteLine("ip3366.net没有获取到代理ip");     }    }   }  }

Redis第三库使用的stackoverflow的 StackExchange.Redis,代理ip不能重复储存,所以采用的数据结构是Set。存的值非常简单就一个ip加上port,也可以存入更多相关信息,感觉没必要。即使有这些其他的信息,也很难发挥作用。RedisHelper.cs如下

public class RedisHelper  {   private static readonly object Locker = new object();   private static ConnectionMultiplexer _redis;   private const string CONNECTTIONSTRING = "127.0.0.1:6379,DefaultDatabase=3";   public const string REDIS_SET_KET_SUCCESS = "set_success_ip";   private static ConnectionMultiplexer Manager   {    get    {     if (_redis == null)     {      lock (Locker)      {       if (_redis != null) return _redis;       _redis = GetManager();       return _redis;      }     }     return _redis;    }   }   private static ConnectionMultiplexer GetManager(string connectionString = null)   {    if (string.IsNullOrEmpty(connectionString))    {     connectionString = CONNECTTIONSTRING;    }    return ConnectionMultiplexer.Connect(connectionString);   }   public static bool InsertSet(string value)   {    var db = Manager.GetDatabase();    return db.SetAdd(REDIS_SET_KET_SUCCESS,value);   }  }

以上是“c#如何批量抓取免费代理并且验证有效性”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI