国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

c#批量抓取免費代理并且驗證有效性的實戰教程

2019-10-29 19:59:45
字體:
來源:轉載
供稿:網友

前言

之前看到某公司的官網的文章的瀏覽量刷新一次網頁就會增加一次,給人的感覺不太好,一個公司的官網給人如此直白的漏洞,我批量發起請求的時候發現頁面打開都報錯,100多人的公司的官網文章刷新一次你給我看這個,這公司以前來過我們學校宣傳招人+在園子里搜招聘的時候發現居然以前招xamarin,挺好奇的,所以就關注過。好吧不說這些了,只是扯扯蛋而已,回歸主題,我想說的是csdn的文章可以通過設置代理ip刷新文章的瀏覽量,所以首先要做的就是這篇文章的主題“使用c#驗證代理ip有效性”。

當然代理IP來源肯定是免費,所以嘛效率一般,從一些免費的代理ip的網頁抓取的代理IP并不一定都是有用的,所以需要我們對我們抓取的代理ip進行驗證,代理ip的有效時間也是有限,從10幾秒到1個小時不限,大多數時間非常短,所以比如說,我們1分鐘需要100個代理ip,那就1分鐘獲取一次,每次獲取100個(這里是理想狀態下的,抓取的代理ip都是有效的),原則上來說抓取下來后應該立即馬上被使用。

當然這篇文章比較基礎,一直覺得爬蟲比較有趣,其實我在爬蟲方面也是個小白,只是做一個簡單的記錄,如果有什么錯誤的地方,希望能提出建議。針對下面幾個問題,我們就可以完成如何驗證代理IP有效性的檢測了。

1.從哪些網頁上可以抓取免費的代理IP?

http://www.xicidaili.com

http://www.ip3366.net

http://www.66ip.cn

百度一下“免費代理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。

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);  } }

總結

明天補上刷新網頁瀏覽量的文章吧,代碼還不夠好,ip的有效性還不高,對多線程的使用還不是很熟練

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 辉县市| 石家庄市| 招远市| 鸡东县| 东安县| 手游| 大新县| 商河县| 历史| 三门县| 抚顺县| 英吉沙县| 大余县| 英超| 隆化县| 盘锦市| 额济纳旗| 保定市| 泽库县| 青州市| 稻城县| 新密市| 旬阳县| 昂仁县| 福建省| 贺州市| 墨江| 新沂市| 揭西县| 肃宁县| 科技| 吐鲁番市| 盱眙县| 河西区| 瑞丽市| 赣州市| 华蓥市| 乌恰县| 太谷县| 城固县| 襄城县|