乾貨丨用相似度演算法分析和解決字型反爬問題

語言: CN / TW / HK

大家好,我是崔慶才。

今天給大家分享我的一位朋友寫的文章,這篇文章利用了相似度演算法來進行了字型反爬相關分析, 解決思路比較 新穎,推薦大家一看,希望對大家有幫助~

如下是正文。

一、什麼是字型反爬?

前言:字型反爬就是將關鍵性資料對應於其他Unicode編碼,瀏覽器使用該頁面自帶的字型檔案載入關鍵性資料正常顯示,而當我們將資料進行復制貼上、爬取操作時,使用的還是標準的Unicode字元對映,解析後就是干擾性資料。簡單的說,字型反爬指的就是瀏覽器頁面上的字元和除錯視窗或者原始碼中的內容,顯示的不一樣,這就是字型反爬!

二、字型反爬案例分析

1、首先開啟我們本次分析的網站,搜尋指定內容,截圖如下所示:

說明: 當我看到這個搜尋結果時,腦子裡一片空白,說實話這型別的反爬手段我還是第一次遇到。但是絲毫不慌,更加激發了我的興趣,我喜歡幹有挑戰的事情!

2、搜尋當前截圖的class屬性stonefont,定位到指定程式碼塊原始碼,截圖如下:

3、分析當前程式碼塊片段,發現一個關鍵url,截圖如下所示:

說明: 初步懷疑這個檔案定義了相關字型的編碼格式,為了驗證我的想法,我特意在網上搜了一下,發現很多字型反爬的網站使用的都是這種技術。我還特意查看了一下網上對當前網站的分析,發現都是很多年前的文章了。這正好激發了我的興趣,探索一下當前新版本的加密手段到底有沒有那麼強。

4、為了便於分析,接下來我們直接上程式碼,進行本地化講解吧,程式碼如下所示:


# -*- coding: utf-8 -*-

# --------------------------------------

# @author : 公眾號:逆向與爬蟲的故事

# --------------------------------------

import re

from typing import Dict



import requests





def start_requests():

headers = {

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',

'Accept-Language': 'zh-CN,zh;q=0.9',

'Cache-Control': 'no-cache',

'Connection': 'keep-alive',

'Pragma': 'no-cache',

'Referer': '',

'Sec-Fetch-Dest': 'document',

'Sec-Fetch-Mode': 'navigate',

'Sec-Fetch-Site': 'same-origin',

'Sec-Fetch-User': '?1',

'Upgrade-Insecure-Requests': '1',

'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36',

'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"',

'sec-ch-ua-mobile': '?0',

'sec-ch-ua-platform': '"macOS"',

}



params = {

'showType': '2',

'offset': '0',

}

proxy: Dict[str, str] = {

"http": "xxx",

"https": "xxx",

}

woff_url: str = "https://xxxx/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/{}"

response = requests.get('https://xxxxx/films', params=params, headers=headers, proxies=proxy)

woff_name = re.findall(r"/font/([A-Za-z0-9]{8}\.woff)", response.text)[0]

if woff_name:

with open("index.html", 'wb') as f:

f.write(response.content)

print("The index file was successfully written. Procedure")

with open(woff_name, 'wb') as b:

response = requests.get(woff_url.format(woff_name))

b.write(response.content)

print("The woff file was successfully written. Procedure")



if __name__ == '__main__':

start_requests()

說明: 我先簡單點寫了一個demo函式,目的是為了下載網站首頁和woff檔案,進行本地化除錯使用。

5、接下來對index檔案、woff檔案進行相關字型引數分析,開啟index檔案,截圖如下:

用正則提取相關欄位,然後與當前截圖進行比對分析,程式碼如下:


items = re.findall(r'<span class="stonefont">(.*?)</span>', response.text)

for item in items:

print(item)

將上面的正則程式碼編輯好後執行截圖如下:

說明:我們可以發現每一個&#xe201型別的文字與index截圖中的int數字相對應,此刻我心裡在想,我們只需要把0-9這幾個數字的型別對應的&#x編碼找到不就解決問題了嗎?但是我經過多次實驗後,發現woff檔案不是固定的,他會隨機變動,也就是這樣的方式根本行不通!接下來,我們去woff檔案中找找,說不定能找到規律呢。

6、對woff檔案進行特殊處理,檢視檔案編碼資訊,程式碼如下所示:


from fontTools.ttLib import TTFont

def process_woff():

font = TTFont('695b7b90.woff')

font.saveXML('695b7b90.xml')

使用上面程式碼處理woff格式的檔案,將woff檔案通過TTFont模組轉為xml格式檔案,開啟xml檔案,截圖如下:

總結:本來我還想在xml檔案中找找規律,但是xml中的id值與我們所需要的int值根本不對應,而且沒有任何規律,除錯多個檔案後,腦袋更亂了。正當我疑惑時,看見了一個座標軸,頓時來了靈感!接下來,開始放大招了。

7、使用matplotlib對woff檔案中的座標軸進行繪圖,程式碼如下所示:

8、程式碼執行後截圖如下所示:

總結: 此刻我想到了一個好方法,那就是把編碼座標軸繪圖的結果儲存到本地,然後使用Tesseract第三方包去識別,接下來,讓我們看看效果如何。

9、使用Tesseract識別圖片中文字,程式碼截圖如下所示:

程式碼執行後,效果如下所示:

總結: 果然沒有我想象的那麼簡單,這裡只是把X、Y軸的座標值匹配出來了,但是圖片裡的9根本匹配不到,也就是說 Tesseract不適用於這類資料匹配。不過也給了我們有用的資訊,X和Y座標如果變動,會干擾圖片的相似度匹配。我們需要把X、Y軸裡的數字在儲存圖片的時候去掉。接下來就進入新的步驟分析了,相似度匹配分析。

三、 圖片相似度匹配(方案一)

1、 使用imagehash均值雜湊AHash演算法對png圖片進行圖片指紋計算,程式碼如下:

2、下載不同的woff檔案並對字型加密編碼座標繪圖後,使用imagehash計算hash指紋如下所示:

總結:分析上面兩張截圖,我們發現20張照片的hash指紋,有相同的結果,也有不同的結果。得出結論:通過圖片hash指紋的方式去判斷不準確,我們應該計算圖片hash指紋的相似度閾值,這樣效果應該不錯。

3、先對10張圖片進行人工打標籤,判斷出每一張圖片對應的int值,截圖如下所示:

4、構建程式碼,計算這10張圖片的平均雜湊(不要轉為字串型別),程式碼如下所示:

程式碼執行後計算的圖片hash雜湊如下:

說明: 每一個hash雜湊是由Resize=>8*8的二維陣列組合而成的,並且陣列內容只能是True、False,也就是0、1。

5、構建函式,計算出兩張圖片的相似度閾值,設定最大閾值為3,截圖如下:

說明:將新的圖片計算平均hash雜湊與之前人工打好標籤的hash雜湊值進行比較,如果閾值小於3,則表示他們極度相識。為了驗證我們的演算法效果,接下來進行實戰演練。

6、設定好圖片hash閾值程式碼後,接下來對需要轉換的欄位進行對映編寫相關程式碼,截圖如下:

7、此刻所有的程式碼基本已經構建完成,讓我們執行起來看看效果:

開啟指定網頁,截圖如下:

總結:觀察上面兩張截圖,我們發現程式碼列印的結果和網站裡的內容完全一致,此刻大功告成,我們使用imagehash相似度匹配計算閾值的方法,能夠還原出經過編碼後的真正字型了。接下來,讓我們進入文字相似度還原字型加密環節吧!

四、文字 相似度匹配(方案二)

1、 使用imagehash均值雜湊AHash演算法對png圖片進行圖片指紋 計算,程式碼如下:


def get_image_hash(self, img_file):

"""average_hash """

hash = imagehash.average_hash(Image.open(img_file))

return str(hash)

2、選擇單個woff檔案中的0-9圖片,通過計算圖片hash的方式,分別給每張圖片的hash值打上標籤數字,對應關係如下圖所示:

3、構建程式碼,使用SequenceMatcher計算兩張圖片的hash字串文字相識度閾值,截圖如下:

說明: 將新的圖片計算圖片平均hash值與之前人工打好標籤的hash值進行文字相似度閾值計算,如果閾值大於90,則表示他們極度相識。 為了驗證我們的演算法效果,接下來進行實戰演練。為了不對之前的圖片相似度資料造成干擾,我們直接請求第二頁的資料。

4、相關程式碼構建完成後,啟動文字相似度匹配演算法功能,截圖如下:

開啟指定網頁,截圖如下:

總結: 觀察上面兩張截圖,我們發現程式碼列印的結果和網站裡的內容完全一致,此刻大功告成,我們可以通過文字相似度匹配計算閾值的方法還原字型加密。到這裡本次分享就結束了,感謝大家的耐心閱讀!

五、心得分享和總結

通過本次案例分享,我發現有些技術點不是難,而是沒接觸過(hhh接觸過也不一定會)。這也充分說明了要多讀書、多學習,以便於遇到新的問題時能夠從容應對。 今天分享到這裡就結束了,歡迎大家關注下期文章,我們不見不散:fuelpump:️

End

崔慶才的新書 《Python3網路爬蟲開發實戰(第二版)》 已經正式上市了!書中詳細介紹了零基礎用 Python 開發爬蟲的各方面知識,同時相比第一版新增了 JavaScript 逆向、Android 逆向、非同步爬蟲、深度學習、Kubernetes 相關內容,‍同時本書已經獲得 Python 之父 Guido 的推薦,目前本書正在七折促銷中!

內容介紹: 《Python3網路爬蟲開發實戰(第二版)》內容介紹

掃碼購買

好文和朋友一起看~