貓眼電影某頁面動態字體bypass

注意本文的版權聲明。

0x00 起手

主要介紹了筆者對貓眼電影https://piaofang.maoyan.com/?ver=normal的動態字體反爬的分析工作和處理。這種字體反爬的手段還經常運用在小說網站中,優點是因爲字體非常規字體,即便使用了瀏覽器模擬訪問,也取不到直接數據。不過筆者目前基本已經可以做到自動完成數字和字母,漢字有待進一步測試調試。

當然,貓眼其實有一個更好爬的頁面:https://piaofang.maoyan.com/dashboard。這裏只是知難而上地介紹技術,不爬什麼票房。

0x01 取到字體

在這裏插入圖片描述

這裏最開始的截圖,瀏覽器自帶調試器network下的瀏覽器渲染預覽,在第一次請求目標URL的時候,數據包已經取回了關鍵位置的內容。不過很明顯的,可以看到有些字體和其他的不一樣,主要是數字發生了變化。通常這個樣子說明是數據包裏自帶有JS或者CSS,並執行了。直接複製這些數據,會變成方塊,和Linux下丟失了不支持中文時的表現得差不多。看源碼,這裏其實是一種編碼。
在這裏插入圖片描述
向上定位,找到了加載渲染的JS,很明顯有一個base64編碼的標記。後面的數據通過解碼得到的是一個對應ASCII爲wOFF開頭的bin數據,這個開頭是一種字體文件格式的魔數。這種編碼對應了這個字體中的某個字符,然後瀏覽器支持這種標準,就會渲染出來對應的字體。
在這裏插入圖片描述
然後寫腳本發送請求數據,注意數據包一定要有UA頭才能取到數據。經過一段時間這些字體編碼是會變化的,這就是一開頭提到的動態。使用工具提取字體xml內容,因爲使用python編寫,所以作者在這裏是調用fontTools模塊提取。

a = base64.b64decode(b64data)
with open('tmp','wb') as f:
    f.write(a)
tmp = TTFont('tmp')
tmp.saveXML('end.xml')

xml裏每個字符有一個標籤,子標籤中會有字體定型的關鍵座標信息。下一步的工作就是把這些點取出來,有了這些點,字體的骨架就有了。最開始使用的辦法是通過python中的matplotlib模塊進行畫線,matplotlib本身的強大畫圖功能對於這種工作來說是小試牛刀。不過有幾個字符因爲點的順序,總是會有多餘的連線,比如0這樣的先畫外圈再畫內圈,內外之間就多一條連線,而且兩個圈還不閉合。這個問題擱置了一段時間沒法解決。當時,有兩種處理辦法:一種是圖片出來之後人工改一改圖片名,然後再用程序替換字體。另外一個是使用OCR,不過這時還是些點或者一些線,根本不符合OCR應用的場景。

0x02 渲染字體

後來翻看matplotlib gallery的時候看到matplotlib中plot的.fill()函數可以畫封閉圖形,比如給出一個環上的點集,可以此畫出一個圈。於是決定試試這個函數能否畫出來想要的結果,運行之後還是不錯的。雖然沒有任何抗鋸齒機制,就是單純地描了描點,不過已經解決了關鍵問題。推薦使用黑色填充,和白色的地面成對比,後面處理效果更好。瀏覽器如何把字體渲染得那平滑的,查了一些算法都沒有詳細的說明,歡迎大佬不吝賜教。
在這裏插入圖片描述
之後就是如何讓OCR識別了。一般OCR可以識別的字體都比較小。是數字的話,應當注意高度比寬度大一些,顯得瘦高一些。這兩個參數的變化十分影響識別的效率,通常長/寬==1的情況沒有長/寬 > 1的好。當然做些預處理結果可能會更好。對於貓眼電影來說,變化的字體都是數字,識別成了O或者o其實可能是0。這裏使用了tesseract。從前面xml中取到映射關係,直接變換過來,就可以替換編碼爲正常數字了。(長寬比和OCR用的參數非常重要)
在這裏插入圖片描述

0x03 後續處理

關於動態字體替換了漢字的情況,目前沒有測試,推測性質應該差不多。極端情況下,多采集樣本,人工標記做成字體訓練OCR增強它的識別力應該能對付了,畢竟不是手寫字識別。

只要頁面能夠被瀏覽,編碼或者未經數學驗證別出心裁自創的加密都不可能防得住,bypass只是時間的問題。曾經煎蛋被爬蟲毒害得很深,他們自己寫了一個加密,後來逆出來了。現在知道這些徒勞,只是用base64編碼阻擋一下通用爬蟲和初學者。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章