反擊“貓眼電影”網站的反爬蟲策略

來源:互聯網
上載者:User

標籤:程式   顯示   params   ==   rip   mat   spi   spider   方法   

0×01 前言

前兩天在百家號上看到一篇名為《反擊爬蟲,前端工程師的腦洞可以有多大?》的文章,文章從多方面結合實際情況列舉了包括貓眼電影、美團、去哪兒等大型電商網站的反爬蟲機制。的確,如文章所說,對於一張網頁,我們往往希望它是結構良好,內容清晰的,這樣搜尋引擎才能準確地認知它;而反過來,又有一些情景,我們不希望內容能被輕易擷取,比方說電商網站的交易額,高等學校網站的題目等。因為這些內容,往往是一個產品的生命線,必須做到有效地保護。這就是爬蟲與反爬蟲這一話題的由來。本文就以做的較好的“貓眼電影”網站為例,搞定他的反爬蟲機制,輕鬆爬去我們想要的資料!

0×02 常見反爬蟲

從功能上來講,爬蟲一般分為資料擷取,處理,儲存三個部分。而作為程式員的我們只關心資料擷取部分,處理什麼的還是交給那些資料分析師去搞吧。

一般來說,大多數網站會從三個方面反爬蟲:使用者請求的Headers,使用者行為,網站目錄和資料載入方式。前兩種比較容易遇到,大多數網站都從這些角度來反爬蟲,而第三種則相對比較特殊,一些應用ajax的網站會採用,這樣無疑會增大了爬蟲爬取的難度。

然而,這三種反爬蟲策略則早已有應對的方法和策略。如果遇到了從使用者請求的Headers反爬蟲機制,可以直接在爬蟲中添加Headers,將瀏覽器的User-Agent複製到爬蟲的Headers中;或者將Referer值修改為目標網站網域名稱。對於檢測Headers的反爬蟲,在爬蟲中修改或者添加Headers就能很好的繞過。對於基於使用者行為的反爬蟲其實就是通過限制同一IP短時間內多次訪問同一頁面,應對策略也是很粗暴——使用IP代理,可以專門寫一個爬蟲,爬取網上公開的代理ip,檢測後全部儲存起來。有了大量代理ip後可以每請求幾次更換一個ip,即可繞過這種反爬蟲機制。對於最後一種動態網頁面反爬蟲機制來講,selenium+phantomJS架構能夠讓你在無介面的瀏覽器中類比載入網頁的動態請求,畢竟selenium可是自動化滲透的神器。

0×03 貓眼反爬蟲介紹

介紹完常見的反爬蟲機制,我們回過頭看看我們今天的主角:貓眼電影的反爬蟲是什麼樣的。

對於每日的電影院票價這一重要資料,原始碼中展示的並不是純粹的數字。而是在頁面使用了font-face定義了字元集,並通過unicode去映射展示。簡單介紹下這種新型的web-fongt反爬蟲機制:使用web-font可以從網路載入字型,因此我們可以自己建立一套字型,設定自訂的字元對應表關係表。例如設定0xefab是映射字元1,0xeba2是映射字元2,以此類推。當需要顯示字元1時,網頁的源碼只會是0xefab,被採集的也只會是 0xefab,並不是1:

因此採集者採集不到正確的票價資料:

採集者只能擷取到類似的資料,並不能知道””映射的字元是什麼,實現了資料防採集。而對於正常訪問的使用者則沒有影響,因為瀏覽器會載入css中的font字型為我們渲染好,即時顯示在網頁中。也就是說,除去Image Recognition,必須同時爬取字元集,才能識別出數字。 

查看貓眼的網站源檔案正是如此:

所有的票價資訊都是由動態font字型“加密”後得到的。既然知道了原理,我們就繼續發掘,通過分析網站HTML結構,我們發現網站每次渲染票價的font字型都可以在網頁的script標籤中被找到:

字型是由base64加密後儲存在網頁中的,於是乎,上python:

#將base64加密的font檔案解密轉存本地font = re.findall(r"src: url\(data:application/font-woff;charset=utf-8;base64,(.*?)\) format",response_all)[0]fontdata=base64.b64decode(font)  file=open(‘/home/jason/workspace/1.ttf‘,‘wb‘)  file.write(fontdata)  file.close()  

我們在爬取時將font檔案解密後儲存在本機存放區為ttf檔案,留做備用。

前文提到過這種web-font定義了字元集,要通過unicode去映射展示,所以,我們要構建ttf字型檔中unicode映射出來的字元字典:

python代碼:

import fontforgedef tff2Unicode():#將字型映射為unicode列表    filename = ‘/home/jason/workspace/1.ttf‘    fnt = fontforge.open(filename)    for i in fnt.glyphs():        print i.unicode

我們猜測映射關係如下:

還記得嘛,第三張圖我們爬取到的資料是“繡春刀·修羅戰場 341189 2017-07-20 6號廳 2D 國語 11:10 ”,我們將“&#”替換成“0”後對應上表得出的票價不是剛好是“29”嘛!

python代碼:

tmp_dic={}ttf_list = []def creatTmpDic():#建立映射字典    tmp_dic={}    ttf_list = []    num_list = [-1,-1,0,1,2,3,4,5,6,7,8,9]    filename = ‘/home/jason/workspace/1.ttf‘    fnt = fontforge.open(filename)    ttf_list = []    for i in fnt.glyphs():        ttf_list.append(i.unicode)    tmp_dic = dict(zip(ttf_list,num_list))#構建字典    return tmp_dic,ttf_listdef tff2price(para = ";",tmp_dic={},ttf_list = []):#將爬取的字元對應表為字典中的數字    tmp_return = ""    for j in para.split(";"):        if j != "":            ss = j.replace("&#","0")            for g in ttf_list:                if (hex(g) == ss):                    tmp_return+=str(tmp_dic[g])    return tmp_return

好的,到此,我們已經可以說已經完成了對票價“加密”資料的破解啦~還是有點小小的成就感呢!但是,這裡面還是有個很坑的地方:開發人員已經想到採集者可以通過分析,知道每一個映射代表的意思,從而進行採集後轉換處理,所以我們每次訪問都是隨機得到一種字型,而且開發人員還定期更新一批字型檔和映射表用來加大採集的難度,所以我們在採集的過程中不得不每採集一個頁面就更新一次本地的該網頁的web-font字型,無疑會大大增加爬蟲的爬取成本和爬取效率,所以從一定意義上確實實現了反爬蟲。

參考文獻:

http://blog.csdn.net/fdipzone/article/details/68166388

https://baijiahao.baidu.com/s?id=1572788572555517&wfr=spider&for=pc

https://zhuanlan.zhihu.com/p/20520370?columnSlug=python-hacker

反擊“貓眼電影”網站的反爬蟲策略

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.