Python刷票小腳本——網絡人氣獎?很差意思,我要了

零、前言

最近參加微軟的kinect大賽,報名以後發現有一個網絡投票,票數最多的項目能夠獲得網絡人氣獎。html

這種事,必然是要搞一搞!編程

說幹就幹。瀏覽器

 

 

 

說明:因爲本人過於懶惰,因此就不截圖了,讓你們失望了!服務器

重點看一下思想就能夠了。cookie

 

 

1、探查敵情

第一步先搞清楚投票的具體流程以及可能的限制條件。網絡

通過研究以後,總結以下:less

  • 投票須要登陸
  • 註冊賬號須要驗證郵箱
  • 登陸不須要驗證碼
  • 每一個賬號一天能夠投一次票,票數能夠選擇,從0~10
  • 投票不須要驗證碼

 

注意到紅字了是吧,這就是最關鍵的地方了。ide

 

好了,咱們的初步思路就出來了:工具

手動註冊好賬號——代碼模擬用戶登陸——登陸以後進行投票網站

 

思路出來了,下面就是工具的選擇。

 

2、工欲利其事。。。

語言嘛必然是我愛的Python。

工具的話,以前其實作過模擬登陸,簡單來講就是用一個模擬瀏覽器的Python插件,而後進行各類模擬用戶操做,好比點擊按鈕啊輸入信息啊之類的。

可是這類插件主要有兩大問題:

  1. headless的不多
  2. 基本上對於HTML頁面的操做只能應用於form

 

headless是什麼呢,能夠簡單理解爲後臺操做。若是作不到headless,那麼你運行的時候其實仍是須要打開一個瀏覽器,只不過腳本會操做瀏覽器。

因此咱們能夠看到,作不到headless的話,不只看起來很是低端(想象一下電腦屏幕上開着一個瀏覽器,而後自動輸入東西,而你之只能傻坐着什麼都不能作),而且使用起來很不方便,好比在沒有圖形界面的系統就沒法使用了。

 

只能應用於form是什麼意思呢,咱們拿jQuery來對比吧。jQuery能夠選擇全部HTML裏出現的東西,可是隻能應用於form就意味着只能操做表單,對於其餘元素就無能爲力了。我不知道爲何會出現這種狀況,多是插件底層有一些限制吧,反正大部分插件都只能操做form。

 

給你們提供三個方案以供參考吧:

 

  • Ghost.py 支持headless而且能夠操做全部元素,甚至能夠運行js,你就知道這個有多強大了。惟一缺點——依賴PyQt或者PySide,你裝一下這倆貨就知道了,簡直折磨死人。因此若是你不想折騰的話,仍是不要用這個了。
  • splinter  半支持headless——splinter默認是不支持headless,可是能夠在使用zope的一個插件的前提下headless,由於我用的是默認的,因此具體怎麼作到headless沒有研究,感興趣的本身搞搞吧。不過估計八成不給力。。。splinter的功能一樣很強大,能夠操做全部元素。
  • mechanize  支持headless可是隻能操做form

 

大概就是這樣。

 

3、Just Do It

重複一下咱們的思路:

登陸——投票

由於我決定採用headless的方案,因此就使用mechanize。

登陸的話沒問題,登陸框原本就是form。投票嘛。。。先放着!咱們先把登陸搞定。

 

直接上代碼:

# coding:utf-8
import cookielib import mechanize import urllib br = mechanize.Browser() cj = cookielib.LWPCookieJar() br.set_cookiejar(cj) br.open('http://k4w.cn/user/index.html') br.select_form(nr=0) br.form['mail'] = 'xxxx@xxx.com' br.form['password'] = 'xxxxxxx' br.submit()

cookielib是用來操做cookie的。由於咱們登陸以後須要跳轉到投票頁面,若是咱們不保留cookie,那麼網站就會把咱們當作未登陸——別忘了,你如今是用代碼在模擬登陸,因此不要覺得他會自動給你保存cookie。

 

代碼很簡單吧,我就不解釋了,總之,打開頁面——輸入用戶名密碼——提交

 

能夠輸出一下結果看看:

.....同上..... response = br.submit() print response.read()

咱們能夠看到輸出的HTML中有「xxx,歡迎你」這樣的字樣,說明已經成功登陸了

 

下面就是重頭戲了——如何投票。

 

先具體化投票的操做:

從下拉列表裏選擇「10」,而後點擊肯定。

咱們已經知道,mechanize只能操做form,對於其餘元素是無能爲力的,因此咱們不能直接來模擬人的操做。

那麼該怎麼辦呢?

 

你們先思考5秒鐘

 

 

 

。。。。。。。。

 

 

。。。。。

 

 

。。。

 

 

 

 

好吧我知道你直接翻下來了。

我當時但是思考了半天才想出來的啊!!!

 

咱們能夠換個思路,投票,表面上是人的操做,可是最終發送給服務器的實際上是一個POST請求!因此,咱們能夠跳過模擬操做,直接發送請求!

 

好的,這下思路清晰了。咱們先——等等,咱們POST什麼東西?

投票啊,告訴服務器咱們投票了。

可是代碼是一個很嚴謹的東西,格式不對的話服務器是不認的!

好吧,此次不思考了,直接告訴你答案吧。

 

咱們先手動投一次票,而後查看POST請求中的數據格式。

 

我用的是firebug,打開firebug,而後選擇票數,按肯定按鈕,能夠看到firebug中出來了此次POST請求的具體信息。

咱們點開信息,能夠看到數據的格式:

z_data : 10 id : 99 sid : 78

一下就看出來了嘛!

z_data是票數,id是項目編號,sid。。。好吧我不知道這是什麼。總之就寫78好了。

 

數據格式獲取到了,下面咱們回到代碼中,模擬一個POST請求:

parameters = {'z_data' : '10', 'id' : '99', 'sid' : '78' } # POST data
data = urllib.urlencode(parameters) response = br.open('http://k4w.cn/zone/z_num.html', data)

很簡單吧?

別忘了import urllib!

 

好了,咱們和前面的代碼組合起來實驗一下,看看效果。

發現票數確實增長了,咱們的方法是可行的。

 

而後呢,咱們改一下,加個for循環,這樣就能夠按照咱們設定好的用戶名密碼,自動登陸全部用戶並投票。

 

基本功能就是這樣了,可是使用了幾天以後發現了一個不爽的地方:投票完要想查看票數還得手動打開網頁。若是能直接顯示出來當前票數就行了!

 

因而咱們繼續踏上征程。

 

4、迭代好吃嗎

首先仍是思路:

打開項目頁面——獲取票數——顯示

 

打開頁面咱們已經會了,br.open()就行。顯示也很簡單,print。那麼怎麼獲取票數呢?

給你們介紹一個新工具——BeautifulSoup,靚湯!

我認可名字有點。。。。

無論了,繼續咱們編程之路。

 

靚湯是一個解析HTML的插件,介紹完畢。

 

咱們能夠把獲取到的HTML用靚湯解析一下,而後找到咱們須要的票數對應的那個元素,就能夠獲取票數了。

很簡單是吧!咱們把HTML傳入靚湯。。。。

我靠怎麼出錯了!

Google了半天,原來是HTML中有不規範的標籤,就解析失敗了。

微軟的頁面原來也不符合標準。。。

 

好吧,解析不了,怎麼辦呢?

 

有人給出瞭解決辦法:用lxml。

 

lxml又是個什麼東西?lxml是解析xml的一個插件,可是能夠解析HTML而且,注意啊,而且能夠忽略不規範的標籤。

正好是咱們須要的!

OK,照着官方文檔使用一下~

亮代碼:

br = mechanize.Browser() response = br.open('http://k4w.cn/level_search/1/78/0/0/0.html') page = etree.HTML(response.read().lower().decode('utf-8')) hrefs = page.xpath(u"//span[@class='number n_99']") print "當前票數:" + hrefs[0].text

依然是很簡單不解釋,看看就明白了。

 

好的,這樣咱們整個刷票腳本就完工了~~

 

全部代碼來個合影

# coding:utf-8
import cookielib import mechanize import urllib from lxml import etree all_data = [['username1', 'password1'], ['username2', 'password2']] for i in all_data: br = mechanize.Browser() cj = cookielib.LWPCookieJar() br.set_cookiejar(cj) br.open('http://k4w.cn/user/index.html') br.select_form(nr=0) br.form['mail'] = i[0] br.form['password'] = i[1] br.submit() response = br.open('http://k4w.cn/level_search/1/78/0/0/0.html') parameters = {'z_data' : '10', 'id' : '99', 'sid' : '78' } # POST data
    data = urllib.urlencode(parameters) response = br.open('http://k4w.cn/zone/z_num.html', data) print "%s 投票成功!" % i[0] br = mechanize.Browser() response = br.open('http://k4w.cn/level_search/1/78/0/0/0.html') page = etree.HTML(response.read().lower().decode('utf-8')) hrefs = page.xpath(u"//span[@class='number n_99']") print "當前票數:" + hrefs[0].text

搞定。

 

5、總結

咱們使用了:

  • mechanize  模擬用戶操做  模擬POST請求
  • firebug  獲取POST數據格式
  • lxml  解析HTML內容

 

咱們實現了:

  • 自動登陸
  • 自動投票
  • 輸出票數

 

好了,下面只要把這個腳本放到服務器上,而且設置一下天天運行就能夠了。

相關文章
相關標籤/搜索