春運刷票的那些年

其實這篇也可以叫:《那些年,我們一起刷酷訊》。

每年春運買火車票這事兒都能讓京飄的同學們愁上個把月,其實每年也沒看到誰回不去。04、05想找一張二手票很難,263跳蚤市場,水木,貼吧到處去淘。到了06春節前,事情有了轉機,出現了這麼個網站kooxoo.com,發跡於水木清華bbs,做的事情就是垂直搜索二手火車票轉讓信息,這個網站就是如今大名鼎鼎的酷訊。

刷酷訊也不那麼容易,往往刷到了二手信息要不電話打不通,要不加價高的離譜。於是,就有了刷票腳本v1.0。從06到11年這小腳本一直升級到了v6.0,[b][color=red]而功能其實很簡單,開一個網頁每隔三五分鐘刷下酷訊的頁面,和上次的結果做比較,發現新的信息就彈出個提示。[/color][/b]這樣就不用一直盯着網頁看,又能第一時間拿到信息。那些有能量的人,經常會從多個渠道拿到重複的車票,他們並不屑於冒風險賺個幾百差價,這就是最理想的交易對象。

這個小腳本見證了酷訊的變化,也記載了一次次爬與被爬之間小小的博弈。今年火車票全面實名制,我想我和酷訊都可以好好歇歇了,回憶這幾年寫腳本的過程,還是有些技術點蠻有意思的,特別這個小腳本一直使用JavaScript實現,而JS在瀏覽器端受到了諸多限制,趁着還沒全忘,在此記錄一下。

不過先說明下這個小腳本的使用者除了我,也就是部門內的一些同事,刷新頻率也一直沒有改的過於頻繁,對酷訊的影響絕不會超過半個QPS,若說我攻擊還是省省哈。

【跨域XHR】
腳本的實現方案主要分爲兩種:跨域XHR和第三方腳本潛入。06、07年,我用的是前面一種。

我首先想到的是用iframe或者frameset把kx的頁面潛入到我的頁面中,然後我的頁面訪問kx頁面的內容,我們當時的系統中成天這樣幹。但很快發現這不可能,這是我的前端技術生涯中第一次遇到了跨域問題。現在回顧一下各種跨域解決方案,在酷訊無法控制的情況下,這個問題依然是無解的(或許通過加入信任站點?)。好在當時也沒有糾結太久,就轉向了另一個方案。

通過XHR獲取頁面的內容,然後解析文本。大家馬上會想到,依然會有域名大山存在,不過幸運的是,[b][color=red]在IE6裏邊,從文件系統直接打開本地html文件,在允許腳本運行後,是可以發送跨域XHR請求並拿到響應體的[/color][/b]。基於這個事實,後面的一切就簡單的多了,通過XHR獲取數據,然後把數據抽取出來結構化,過一段時間再抽取一次,做比較,有新的,彈出alert提示。

【Firefox GreaseMonkey插件 腳本潛入】
到07進入阿里,不再做IEOnly,開始接觸兼容性開發。我發現了Firefox非常牛X的插件GreaseMonkey,傳說中的“油猴”。[b][color=red]GreaseMonkey的作用就是可以指定在某種類型的url中,自動潛入一個本地腳本運行[/color][/b]。這相當於在我的瀏覽器裏我可以控制其他域名的網頁了。所以在08年,刷票腳本的技術方案改爲腳本潛入。相對與前一個方案,這個方案因爲可以直接訪問對方頁面的Dom樹,不用解析文本,而且從之前分析prototype.js源碼得知Firefox瀏覽器還支持XPath,XML裏類似CSS選擇器,一下子獲取數據變得容易且穩定許多。

後來油猴成爲了我的大玩具,最成功的插件是開心網停車腳本,全自動停車,十分鐘換地方,想貼條那是沒門。當然還有自動貼條腳本,太傷人品,沒有擴散,呵呵。

【GreaseMonkey本地存儲和GlobalStorage】
改爲腳本潛入也不是一點障礙沒有,在跨域XHR方案中,多次獲取的頁面數據統一在內存中,比較起來非常方便。而改爲腳本潛入的模式的V3.0,每次刷新頁面,如何保持數據成了一個重要問題,存在cookie中有些醜陋,而且暴露給對方服務器了。好在[b][color=red]GreaseMonkey插件提供了本地存儲功能,用它記錄前一個頁面的信息,以備後面比較[/color][/b]。我不記得API是什麼了,暫且叫他GMStorage吧,和Html5本地存儲接口差不多。而在09年的v4.0我就直接使用了本地存儲,當時還叫GlobalStorage,而不是LocalStorage。

【GreaseMonkey的安全改進DomWrapper】
GreaseMonkey越來越流行,其潛在的安全問題也是巨大的,隨意安裝GM腳本,你的所有網頁瀏覽行爲,鍵盤輸入都可能被監聽記錄。
09年V4.0開發時,我發現油猴做了一些改變,油猴腳本里拿到的document,不在是真是的document,很多操作變的沒有效果。
這必須Hack一下,我嘗試了幾種辦法,發現[b][color=red]在油猴腳本里邊使用DomScriptElement方法創建一個script節點,另載入一個外部腳本,另外一個腳本的運行不受任何GM的安全限制[/color][/b]。
其實我覺得GM的DomWrapper還不如不做,它迫使人們引入另外一個遠程腳本,也使得腳本開發者更容易的通過改變另外一個腳本的內容神不知鬼不覺的做些壞事。

【酷訊的變化:從堵到疏】
記得07年阿里第一屆網俠大會,酷訊的哥們分享他們如何爬到數據,就神祕的提了一下,藉助前端腳本抓取,我在下邊聽着暗笑~,大家手法是一樣一樣一樣的啊。
隨着年復一年的口碑相傳,用酷訊淘票的人越來越多。我估計類似我的小腳本的各式各樣工具也越來越多。面對這類問題,酷訊明顯的經歷了一個由堵到疏的過程。
某一年,酷訊在請求時帶上了兩個參數,記錄鼠標點擊位置相對搜索按鈕左上角的像素差。
某一年,酷訊不再使用順序的id,每條信息的ID都是一個隨機串,這樣判斷是否有新信息變得麻煩。

但是客戶端沒有祕密而言,這些小手段都可以被輕易化解,估計效果並不是很好。

再後來酷訊可能也注意到沒有太好的辦法堵,就改爲疏導,改爲本身提供這類自刷新功能,有新信息氣泡提示,這樣方便的控制刷新頻率(似乎間隔越來越長),降低服務器的壓力。

在10年的V5.0中,腳本只是簡單的控制自刷新頻率,做更醒目的提示。且更多的利用本地存儲,記錄以往的搜索信息供比對。

【Bookmarklet 腳本潛入】
我最早發現Bookmarklet應用是CSDN的一個轉帖插件,[b][color=red]Bookmarklet的核心是構造一個連接,連接內容是javascript:僞協議,把這個鏈接拖入收藏夾,在任意頁面上點擊這個連接,都會運行js爲協議裏包含的腳本內容,腳本內容常常是通過DomScriptElement引入一個遠程腳本[/color][/b],這樣也達到了腳本潛入的目的。這個技術後來被廣泛應用於各種雲輸入法當中而被大家熟知。
因爲Bookmarklet不限制瀏覽器,酷訊提供了Ajax獲取新信息接口(不用刷整個頁面),IE8支持了LocalStorage,10年的V5.0版本腳本即支持GM也支持BM,刷票腳本再次迴歸IE懷抱。不過BM需要每次點一下,這個還是比GM要麻煩一點點。


【其他網站的分流】
11年的V6.0是腳本效果最差的一年,因爲酷訊的效果感覺不那麼即時了,58這類的網站分流了酷訊的客流。今年大家都不用做這一塊了,不過真心希望業界豐富建站經驗的高手們,能夠承擔12306.cn的建設工作,這個站的體驗和穩定性太次了,其實俺覺得包給淘寶做就挺好,呵。

前面就是這幾年寫刷票腳本的流水賬,不用再做了,大家都釋然吧。
特別感謝酷訊,多年來行善舉造福大家。
祝新老朋友今年順利拿到平價車票,開開心心過大年。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章