使用TaskManager爬取2万条代理IP实现自动投票功能

话说某天心血来潮想到一个问题,朋友圈里面经常有人发投票链接,让帮忙给XX投票,以前呢会很自觉打开链接帮忙投一票。可是这种事做多了就会考虑能不能使用工具来进行投票呢,身为一名程序猿决定研究解决这个问题。于是有了以下思考

1.是否能一个人投多票,如果不行又是什么限制了一人投多票?

答:投票网站限制了一个IP或者一个用户只能投一票,防止恶意刷票行为

2.如果是一个IP一票那是否代表着多个IP就能投多票了呢?

答:答案是肯定的

3.用什么方法能够在代码里面改变自己请求的IP?

答:HTTP请求的时候设置代理IP

4.多个代理IP从哪里获取,获取到之后我又该如何使用代码自动化投票?

答:请看文章后面内容

本篇将介绍TaskManager内置任务-代理IP爬虫实现细节,你需要准备的知识:HtmlAgilityPack解析HTML,Quart.net

代理IP介绍

百度百科介绍:代理(英语:Proxy),也称网络代理,是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端 (一般为服务器)进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击。

目前有很多厂商提供代理IP在线获取,但是很多都是提供几十个试用的,如果想使用更多的代理IP,则需付费购买。这里我找到了一个提供很多代理IP的网站,可以自行百度“代理ip”(以免认为我打广告),或者参考开源TaskManager介绍这篇文章。

有了这么多在线的代理IP可以解决文章开头的问题4了,可是还有个问题这些数据都是网页上的,我在代码里面怎么使用呢?这就用到了HtmlAgilityPack工具包,看名称就能猜到是用来解析HTML的。

HtmlAgilityPack使用

HtmlAgilityPack是一个开源的解析HTML元素的类库,最大的特点是可以通过XPath来解析HMTL,如果您以前用C#操作过XML,那么使用起HtmlAgilityPack也会得心应手。

解析简单的HTML


  1. string HTML = @"<html><head><title>简单解析测试</title></head><body> 
  2.                     <div id='div1' title='div1'
  3.                         <table> 
  4.                              <tr> 
  5.                                 <td>1</td> 
  6.                                 <td title='cn'>cn</td> 
  7.                             </tr> 
  8.                         </table> 
  9.                     </div> 
  10.                 </body></html>"; 
  11.             var doc = new HtmlDocument(); 
  12.             doc.LoadHtml(HTML); 
  13.             //输出页面标题 
  14.             Console.WriteLine("页面title:"+doc.DocumentNode.SelectSingleNode("/html/head/title").InnerText); 
  15.             //获取div1节点  方式1 
  16.             HtmlNode divNode1 = doc.GetElementbyId("div1"); 
  17.             //获取div1节点  方式2 
  18.             HtmlNode divNode2 = doc.DocumentNode.SelectSingleNode("//div[@id='div1']"); 
  19.             //判断节点1和节点2是否相同 
  20.             Console.WriteLine("断节点1和节点2是否相同:" + (divNode1 == divNode2)); 
  21.             //获取页面所有table 
  22.             HtmlNodeCollection tableCollection = doc.DocumentNode.SelectNodes("//table"); 
  23.             Console.WriteLine("页面table数量:"+tableCollection.Count); 
  24.             //获取table下所有td并输出信息 
  25.             HtmlNodeCollection tdCollection = tableCollection[0].SelectNodes("tr/td"); 
  26.             foreach (var td in tdCollection) 
  27.             { 
  28.                 HtmlAttribute atr = td.Attributes["title"]; 
  29.                 Console.WriteLine("td InnerText:" + td.InnerText + " | td title属性值:" + (atr == null ? "" : atr.Value)); 
  30.             } 
  31.             Console.Read(); 

使用TaskManager爬取2万条代理IP实现自动投票功能

代理IP爬虫实现

会了HtmlAgilityPack的一些简单操作之后进入正式爬取过程,由于需要爬取的网页带IP*功能(一段时间请求频率过高*当前IP),在设计过程中我采用了爬取五次自动换代理IP突破网站限制(感觉自己坏坏的)。

使用TaskManager爬取2万条代理IP实现自动投票功能

整体实现逻辑

在.net里面使用WebRequest可以模拟HTTP的get Post请求,最终要的一点能设置请求时使用的代理IP,重点关注我标红的代码


  1. /// <summary> 
  2.         /// 代理使用示例 
  3.         /// </summary> 
  4.         /// <param name="Url"></param> 
  5.         /// <param name="type"></param> 
  6.         /// <returns></returns> 
  7.         public static string GetUrltoHtml(string Url, string type) 
  8.         { 
  9.             try 
  10.             { 
  11.                 System.Net.WebRequest wReq = System.Net.WebRequest.Create(Url); 
  12.  
  13.                 WebProxy myProxy = new WebProxy("192.168.15.11"8015); 
  14.                 //建议连接(代理需要身份认证,才需要用户名密码) 
  15.                 myProxy.Credentials = new NetworkCredential("admin""123456"); 
  16.                 //设置请求使用代理信息 
  17.                 wReq.Proxy = myProxy; 
  18.                 // Get the response instance. 
  19.                 System.Net.WebResponse wResp = wReq.GetResponse(); 
  20.                 System.IO.Stream respStream = wResp.GetResponseStream(); 
  21.                 // Dim reader As StreamReader = New StreamReader(respStream) 
  22.                 using (System.IO.StreamReader reader = new System.IO.StreamReader(respStream, Encoding.GetEncoding(type))) 
  23.                 { 
  24.                     return reader.ReadToEnd(); 
  25.                 } 
  26.             } 
  27.             catch (System.Exception ex) 
  28.             { 
  29.                 //errorMsg = ex.Message; 
  30.             } 
  31.             return ""
  32.         } 

了解如何使用代理IP,离我们的目标又近了一步,下面就是代理IP获取的实现了,由于代码有点多,我这里只贴出重要部分,IpProxyGet.cs源码可到文章末尾自行下载。 


  1. /// <summary> 
  2.   /// 获取总页数 
  3.   /// </summary> 
  4.   /// <returns>总页数</returns> 
  5.   private static int GetTotalPage(string IPURL, string ProxyIp) 
  6.   { 
  7.       var doc = new HtmlDocument(); 
  8.       doc.LoadHtml(GetHTML(IPURL, ProxyIp)); 
  9.       var res = doc.DocumentNode.SelectNodes(@"//div[@class='pagination']/a"); 
  10.       if (res != null && res.Count > 2
  11.       { 
  12.           int page; 
  13.           if (int.TryParse(res[res.Count - 2].InnerText, out page)) 
  14.           { 
  15.               return page; 
  16.           } 
  17.       } 
  18.       return 1
  19.   } 

解析每一页HTML数据


  1. /// <summary> 
  2.        /// 解析每一页数据 
  3.        /// </summary> 
  4.        /// <param name="param"></param> 
  5.        private static void DoWork(object param) 
  6.        { 
  7.            //参数还原 
  8.            Hashtable table = param as Hashtable; 
  9.            int start = Convert.ToInt32(table["start"]); 
  10.            int end = Convert.ToInt32(table["end"]); 
  11.            List<IPProxy> list = table["list"] as List<IPProxy>; 
  12.            ProxyParam Param = table["param"] as ProxyParam; 
  13.  
  14.            //页面地址 
  15.            string url = string.Empty; 
  16.            string ip = string.Empty; 
  17.            IPProxy item = null
  18.            HtmlNodeCollection nodes = null
  19.            HtmlNode node = null
  20.            HtmlAttribute atr = null
  21.            for (int i = start; i <= end; i++) 
  22.            { 
  23.                LogHelper.WriteLog(string.Format("开始解析,页码{0}~{1},当前页码{2}", start, end, i)); 
  24.                url = string.Format("{0}/{1}", Param.IPUrl, i); 
  25.                var doc = new HtmlDocument(); 
  26.                doc.LoadHtml(GetHTML(url, Param.ProxyIp)); 
  27.                //获取所有数据节点tr 
  28.                var trs = doc.DocumentNode.SelectNodes(@"//table[@id='ip_list']/tr"); 
  29.                if (trs != null && trs.Count > 1
  30.                { 
  31.                    LogHelper.WriteLog(string.Format("当前页码{0},请求地址{1},共{2}条数据", i, url, trs.Count)); 
  32.                    for (int j = 1; j < trs.Count; j++) 
  33.                    { 
  34.                        nodes = trs[j].SelectNodes("td"); 
  35.                        if (nodes != null && nodes.Count > 9
  36.                        { 
  37.                            ip = nodes[2].InnerText.Trim(); 
  38.                            if (Param.IsPingIp && !Ping(ip)) 
  39.                            { 
  40.                                continue
  41.                            } 
  42.                            //有效的IP才添加 
  43.                            item = new IPProxy(); 
  44.  
  45.                            node = nodes[1].FirstChild; 
  46.                            if (node != null
  47.                            { 
  48.                                atr = node.Attributes["alt"]; 
  49.                                if (atr != null
  50.                                { 
  51.                                    item.Country = atr.Value.Trim(); 
  52.                                } 
  53.                            } 
  54.  
  55.                            item.IP = ip; 
  56.                            item.Port = nodes[3].InnerText.Trim(); 
  57.                            item.ProxyIp = GetIP(item.IP, item.Port); 
  58.                            item.Position = nodes[4].InnerText.Trim(); 
  59.                            item.Anonymity = nodes[5].InnerText.Trim(); 
  60.                            item.Type = nodes[6].InnerText.Trim(); 
  61.  
  62.                            node = nodes[7].SelectSingleNode("div[@class='bar']"); 
  63.                            if (node != null
  64.                            { 
  65.                                atr = node.Attributes["title"]; 
  66.                                if (atr != null
  67.                                { 
  68.                                    item.Speed = atr.Value.Trim(); 
  69.                                } 
  70.                            } 
  71.  
  72.                            node = nodes[8].SelectSingleNode("div[@class='bar']"); 
  73.                            if (node != null
  74.                            { 
  75.                                atr = node.Attributes["title"]; 
  76.                                if (atr != null
  77.                                { 
  78.                                    item.ConnectTime = atr.Value.Trim(); 
  79.                                } 
  80.                            } 
  81.                            item.VerifyTime = nodes[9].InnerText.Trim(); 
  82.                            list.Add(item); 
  83.                        } 
  84.                    } 
  85.                    LogHelper.WriteLog(string.Format("当前页码{0},共{1}条数据", i, trs.Count)); 
  86.                } 
  87.                LogHelper.WriteLog(string.Format("结束解析,页码{0}~{1},当前页码{2}", start, end, i)); 
  88.            } 
  89.        } 

最终会获取2万多条数据

使用TaskManager爬取2万条代理IP实现自动投票功能

自动投票简单实现

这里使用.net的WebBrowser控件来加载页面,最终效果如下

使用TaskManager爬取2万条代理IP实现自动投票功能


  1. #region 设置代理IP 
  2.         private void button2_Click(object sender, EventArgs e) 
  3.         { 
  4.             string proxy = this.textBox1.Text; 
  5.             RefreshIESettings(proxy); 
  6.             IEProxy ie = new IEProxy(proxy); 
  7.             ie.RefreshIESettings(); 
  8.             //MessageBox.Show(ie.RefreshIESettings().ToString()); 
  9.         } 
  10.         #endregion 
  11.         #region 取消代理IP 
  12.         private void button3_Click(object sender, EventArgs e) 
  13.         { 
  14.             IEProxy ie = new IEProxy(null); 
  15.             ie.DisableIEProxy(); 
  16.         } 
  17.         #endregion 
  18.         #region 打开网页 
  19.         private void button1_Click(object sender, EventArgs e) 
  20.         { 
  21.             string url = txt_url.Text.Trim(); 
  22.             if (string.IsNullOrEmpty(url)) 
  23.             { 
  24.                 MessageBox.Show("请输入要打开的网址"); 
  25.                 return
  26.             } 
  27.             this.webBrowser1.Navigate(url, nullnullnull); 
  28.         } 
  29.         #endregion 

总结

本篇要介绍的内容到此结束了,下面写点我的期待!希望有喜欢的朋友一起来完善TaskManager(完全开源的),使之成为一款能够提高生活便捷 性的工具,添加很多新任务。比如:第二天要下雨或者下雪,发个邮件提醒,带上雨伞…。好了到了放出源代码的时间了。敬请期待下一篇!


来源:51CTO

上一篇:面试题之java缓存总结,从单机缓存到分布式缓存架构


下一篇:代码精准分析在闲鱼接口测试中的应用