1. 程式人生 > >爬蟲之字型反爬(三)汽車之家

爬蟲之字型反爬(三)汽車之家

今天為大家帶來的是字型反爬的另一個案例,汽車之家。與之前不同的是,這裡是對漢字的處理。具體來看下面的分析與程式碼。

首先參考的網站:https://club.autohome.com.cn/bbs/thread/1f05b4da4448439b/76044817-1.html#%23%23

從網站中可以觀察到,它的反爬是這樣的:

  再從網頁原始碼中觀察,發現又是這樣的:

尋找它的字型檔案:

下載儲存到本地。

接下來就是字型分析,同樣的,先檢視字型檔案:

這裡定義兩個列表,一個為漢字列表,一個為編碼列表,他們之間的對應關係是按順序的,即列表的索引,如下所示:

 觀察後發現,字典中的鍵值並沒有規律和特殊性,還是得通過xml檔案觀察不同字型檔案的區別,生成xml檔案程式碼如下:

from fontTools.ttLib import TTFont
from io import BytesIO

url_ziti = '字型檔案地址'
ziti = requests.get(url_ziti)
# 下載ttf字型檔案,然後通過BytesIO轉化為記憶體檔案,使用TTFont處理
font = TTFont(BytesIO(ziti.content))
cmap = font.getBestCmap()

font.saveXML(r'C:..\qiche1.xml')

接下來還是放兩張圖大家感受一下:

這是相同漢字“大”在不同xml檔案中的物件,可以發現,同一漢字的物件是不相同的,區別在於物件中每個座標的差值小於40,於是當有新的字型檔案時只需要對比同一漢字的編碼其物件的差值是否小於40,如果小於就得到對應的漢字。 

如果大家還沒有理解,在放兩張圖讓大家感受一下:

鐺鐺鐺鐺!!就是你看到的那樣,這兩個漢字細微的差別就是 每個x,y差值的意義。

對比編碼物件的程式碼如下所示:

def comp(l1,l2):#定義一個比較函式,比較兩個列表的座標資訊是否相同
    if len(l1)!=len(l2):
        return False
    else:
        mark= 1
    for i in range(len(l1)):
        if abs(l1[i][0]-l2[i][0])< 40 and abs(l1[i][1]-l2[i][1])< 40:
            pass
        else:
            mark= 0
            break
    return mark

font1 = TTFont(r'C:..\qiche1.ttf')
font2 = TTFont(r'C:..\qiche2.ttf')
tup1=[] #儲存38個字元的(x,y)資訊
for uni in u_list:
    p=font1['glyf'][uni].coordinates #獲取物件的x,y資訊
    tup1.append(list(p))
tup2=[]
for i in uni_list2:
    p=font2['glyf'][i].coordinates
    tup2.append(list(p))
n2= 0
x_list=[]
for d in tup1:
    n2+= 1
    n1= 0
    for a in tup2:
        n1+= 1
        if comp(a,d):
            print(uni_list2[n2-1],word_list[n1-1])
            x_list.append(word_list[n1 -1])

 對比過後,打印出字型2編碼對應的每一個漢字,結果如下圖所示:

與字型二中的內容一致,可見這樣的判斷是符合要求的(如果大家覺得是偶然因素,可以對比多個字型,看最後的結果是否符合)

字型反爬暫時告一段落,這三個案例是由易到難的一個過程,本質就是尋找一種對映關係,從而在不同的字型檔案也能找到對應字元。