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
- string html = @"<html><head><title>簡單解析測試</title></head><body>
- <div id='div1' title='div1'>
- <table>
- <tr>
- <td>1</td>
- <td title='cn'>cn</td>
- </tr>
- </table>
- </div>
- </body></html>";
- var doc = new htmldocument();
- doc.loadhtml(html);
- //輸出頁面標題
- console.writeline("頁面title:"+doc.documentnode.selectsinglenode("/html/head/title").innertext);
- //獲取div1節點 方式1
- htmlnode divnode1 = doc.getelementbyid("div1");
- //獲取div1節點 方式2
- htmlnode divnode2 = doc.documentnode.selectsinglenode("//div[@id='div1']");
- //判斷節點1和節點2是否相同
- console.writeline("斷節點1和節點2是否相同:" + (divnode1 == divnode2));
- //獲取頁面所有table
- htmlnodecollection tablecollection = doc.documentnode.selectnodes("//table");
- console.writeline("頁面table數量:"+tablecollection.count);
- //獲取table下所有td并輸出信息
- htmlnodecollection tdcollection = tablecollection[0].selectnodes("tr/td");
- foreach (var td in tdcollection)
- {
- htmlattribute atr = td.attributes["title"];
- console.writeline("td innertext:" + td.innertext + " | td title屬性值:" + (atr == null ? "" : atr.value));
- }
- console.read();
代理ip爬蟲實現
會了htmlagilitypack的一些簡單操作之后進入正式爬取過程,由于需要爬取的網頁帶ip封鎖功能(一段時間請求頻率過高封鎖當前ip),在設計過程中我采用了爬取五次自動換代理ip突破網站限制(感覺自己壞壞的)。
整體實現邏輯
在.net里面使用webrequest可以模擬http的get post請求,最終要的一點能設置請求時使用的代理ip,重點關注我標紅的代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/// <summary> /// 代理使用示例 /// </summary> /// <param name="url"></param> /// <param name="type"></param> /// <returns></returns> public static string geturltohtml( string url, string type) { try { system.net.webrequest wreq = system.net.webrequest.create(url); webproxy myproxy = new webproxy( "192.168.15.11" , 8015); //建議連接(代理需要身份認證,才需要用戶名密碼) myproxy.credentials = new networkcredential( "admin" , "123456" ); //設置請求使用代理信息 wreq.proxy = myproxy; // get the response instance. system.net.webresponse wresp = wreq.getresponse(); system.io.stream respstream = wresp.getresponsestream(); // dim reader as streamreader = new streamreader(respstream) using (system.io.streamreader reader = new system.io.streamreader(respstream, encoding.getencoding(type))) { return reader.readtoend(); } } catch (system.exception ex) { //errormsg = ex.message; } return "" ; } |
了解如何使用代理ip,離我們的目標又近了一步,下面就是代理ip獲取的實現了,由于代碼有點多,我這里只貼出重要部分,ipproxyget.cs源碼可到文章末尾自行下載。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/// <summary> /// 獲取總頁數 /// </summary> /// <returns>總頁數</returns> private static int gettotalpage( string ipurl, string proxyip) { var doc = new htmldocument(); doc.loadhtml(gethtml(ipurl, proxyip)); var res = doc.documentnode.selectnodes( @"//div[@class='pagination']/a" ); if (res != null && res.count > 2) { int page; if ( int .tryparse(res[res.count - 2].innertext, out page)) { return page; } } return 1; } |
解析每一頁html數據
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
/// <summary> /// 解析每一頁數據 /// </summary> /// <param name="param"></param> private static void dowork( object param) { //參數還原 hashtable table = param as hashtable; int start = convert.toint32(table[ "start" ]); int end = convert.toint32(table[ "end" ]); list<ipproxy> list = table[ "list" ] as list<ipproxy>; proxyparam param = table[ "param" ] as proxyparam; //頁面地址 string url = string .empty; string ip = string .empty; ipproxy item = null ; htmlnodecollection nodes = null ; htmlnode node = null ; htmlattribute atr = null ; for ( int i = start; i <= end; i++) { loghelper.writelog( string .format( "開始解析,頁碼{0}~{1},當前頁碼{2}" , start, end, i)); url = string .format( "{0}/{1}" , param.ipurl, i); var doc = new htmldocument(); doc.loadhtml(gethtml(url, param.proxyip)); //獲取所有數據節點tr var trs = doc.documentnode.selectnodes( @"//table[@id='ip_list']/tr" ); if (trs != null && trs.count > 1) { loghelper.writelog( string .format( "當前頁碼{0},請求地址{1},共{2}條數據" , i, url, trs.count)); for ( int j = 1; j < trs.count; j++) { nodes = trs[j].selectnodes( "td" ); if (nodes != null && nodes.count > 9) { ip = nodes[2].innertext.trim(); if (param.ispingip && !ping(ip)) { continue ; } //有效的ip才添加 item = new ipproxy(); node = nodes[1].firstchild; if (node != null ) { atr = node.attributes[ "alt" ]; if (atr != null ) { item.country = atr.value.trim(); } } item.ip = ip; item.port = nodes[3].innertext.trim(); item.proxyip = getip(item.ip, item.port); item.position = nodes[4].innertext.trim(); item.anonymity = nodes[5].innertext.trim(); item.type = nodes[6].innertext.trim(); node = nodes[7].selectsinglenode( "div[@class='bar']" ); if (node != null ) { atr = node.attributes[ "title" ]; if (atr != null ) { item.speed = atr.value.trim(); } } node = nodes[8].selectsinglenode( "div[@class='bar']" ); if (node != null ) { atr = node.attributes[ "title" ]; if (atr != null ) { item.connecttime = atr.value.trim(); } } item.verifytime = nodes[9].innertext.trim(); list.add(item); } } loghelper.writelog( string .format( "當前頁碼{0},共{1}條數據" , i, trs.count)); } loghelper.writelog( string .format( "結束解析,頁碼{0}~{1},當前頁碼{2}" , start, end, i)); } } |
最終會獲取2萬多條數據
自動投票簡單實現
這里使用.net的webbrowser控件來加載頁面,最終效果如下
#region 設置代理ip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
private void button2_click( object sender, eventargs e) { string proxy = this .textbox1.text; refreshiesettings(proxy); ieproxy ie = new ieproxy(proxy); ie.refreshiesettings(); //messagebox.show(ie.refreshiesettings().tostring()); } #endregion #region 取消代理ip private void button3_click( object sender, eventargs e) { ieproxy ie = new ieproxy( null ); ie.disableieproxy(); } #endregion #region 打開網頁 private void button1_click( object sender, eventargs e) { string url = txt_url.text.trim(); if ( string .isnullorempty(url)) { messagebox.show( "請輸入要打開的網址" ); return ; } this .webbrowser1.navigate(url, null , null , null ); } #endregion |
總結
本篇要介紹的內容到此結束了,下面寫點我的期待!希望有喜歡的朋友一起來完善taskmanager(完全開源的),使之成為一款能夠提高生活便捷 性的工具,添加很多新任務。比如:第二天要下雨或者下雪,發個郵件提醒,帶上雨傘…。好了到了放出源代碼的時間了。敬請期待下一篇!