Python爬蟲入門教程 63-100 Python字體反爬之一,沒辦法,這個必須寫,反爬第3篇

背景交代

在反爬圈子的一個大類,涉及的網站其實蠻多的,目前比較常被爬蟲coder欺負的網站,貓眼影視,汽車之家,大衆點評,58同城,天眼查…還是蠻多的,技術高手千千萬,總有五花八門的反爬技術出現,對於爬蟲coder來說,幹!就完了,反正也996了~

作爲一個系列的文章,那免不了,依舊拿貓眼影視“學習”吧,爲什麼?因爲它比較典型~

貓眼影視

打開貓眼專業版,常規操作,谷歌瀏覽器,開發者工具,抓取DOM節點,

https://piaofang.maoyan.com/?ver=normal

注意下圖所有的數字位置,在DOM結構中,都是方塊。
在這裏插入圖片描述

字體反爬掃盲

字體反爬,是一種常見的反爬技術,網站採用了自定義的字體文件,在瀏覽器上正常顯示,但是爬蟲抓取下來的數據要麼就是亂碼,要麼就是變成其他字符。採用自定義字體文件是CSS3的新特性,熟悉前端的同學可能知道,就是font-face屬性

一些重要破解素材的收集

找到font-family屬性,查看設置的內容,發現是cs字體,這明顯是自定義字體了,在網頁中檢索cs
python3反爬
在頁面的HTML源碼中找到了字體的定義
python3反爬
注意文件的開頭是base64 表示文件進行過base64編碼,需要進行解碼,然後在保存成ttf字體文件

上述截圖中有個woff格式

Web開放字體格式(Web Open Font Format,簡稱WOFF) 是一種網頁所採用的字體格式標準。此字體格式發展於2009年,現在正由萬維網聯盟的Web字體工作小組標準化,以求成爲推薦標準。此字體格式不但能夠有效利用壓縮來減少檔案大小,並且不包含加密也不受DRM(數位著作權管理)限制。

解碼操作

import base64

font_face = "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"

print(len(font_face))

b = base64.b64decode(font_face)
with open('font.ttf','wb') as f:
    f.write(b)

對於ttf文件的處理,有3種方式,第一種使用軟件 FontCreator可以直接打開ttf文件,第二種使用Python第三方庫fontTools,借用這個庫也可以操作ttf文件,第三種使用百度的fontstore, http://fontstore.baidu.com/static/editor/index.html

FontCreator 軟件查找這個就比較簡單了

你可以自行百度尋找,也可以直接打開我的百度網盤下載

鏈接: https://pan.baidu.com/s/1ZyWwk37hNeo0vIsTqdK2fg 提取碼: kk2h

安裝完畢,直接試用即可,也可以採用國家支持的和諧方法,進行和諧
在這裏插入圖片描述
查閱一下sources裏面的html編碼

在這裏插入圖片描述
數字進行比對
在這裏插入圖片描述
順便把這個地方的編碼對應關係記錄一下,方便後續操作

'uniE481': '7',
'uniE0AA': '4', 
'uniF71E': '9', 
'uniE767': '1', 
'uniE031': '5', 
'uniE4BD': '2',
'uniF2AA': '3',
'uniE2E3': '6', 
'uniE3C9': '8', 
'uniEA65': '0'

數字比對完全沒有問題3.69億
sh

開始編碼破解字體反爬

有的網頁嵌套了多套字體,增加了反爬的成本,屆時自行研究即可

利用fontTools可以獲取每一個字符對象,這個對象你可以簡單的理解爲保存着這個字符的形狀信息。
而且編碼可以作爲這個對象的id,具有一一對應的關係。
類似貓眼電影,多套字體對應的字符的編碼是變化的,但是字符的形狀是不變的,也就是說這個對象是不變的。

通過fontTools進行解析字庫文件

安裝fonttools

pip install fonttools

fontTools庫詳解: https://darknode.in/font/font-tools-guide/

基本使用

from fontTools.ttLib import TTFont

font = TTFont('font.ttf')
font.saveXML('01.xml')

打開 xml 文件

開頭顯示的是全部編碼,注意這裏的ID是編號,千萬不要當成對應的數字
在這裏插入圖片描述
下面對應的是字體信息,計算機只需要知道黑白像素點即可
在這裏插入圖片描述
注意事項,寫代碼的時候需要注意一下
在這裏插入圖片描述
在這裏插入圖片描述

關於貓眼的字體反爬做個總結

在實操中,你會發現貓眼電影,每次刷新字符編碼都是變化的,但是字體的對象,也就是像素點是一致的。
在這裏插入圖片描述
你可以通過第一次下載一個字體文件base_font.ttf,並把對應編碼的記下來,當第二次刷新頁面之後,重新抓取字體文件online_font.ttf ,對比兩個字體文件中的對象信息,如果對象是一樣的,那麼就可以知道對應的數字了。

首次獲取字體文件

# 本地已經下載好的字體處理
base_font = TTFont('font.ttf') #打開本地的ttf文件

base_uni_list = base_font.getGlyphOrder()[2:]   # 獲取所有編碼,去除前2個,可查看前文圖示

# 寫出第一次字體文件的編碼和對應字體
origin_dict = {'uniE481': '7', 'uniE0AA': '4', 'uniF71E': '9', 'uniE767': '1', 'uniE031': '5', 'uniE4BD': '2','uniF2AA': '3', 'uniE2E3': '6', 'uniE3C9': '8', 'uniEA65': '0'}

獲取在線字體

# 獲取刷新之後在線的字體

# 獲取字體文件的base64編碼
online_ttf_base64 = re.findall(r"base64,(.*)\) format", response)[0]
online_base64_info = base64.b64decode(online_ttf_base64)
with open('online_font.ttf', 'wb')as f:
    f.write(online_base64_info)
online_font = TTFont('online_font.ttf')  # 網上動態下載的字體文件。

online_uni_list = online_font.getGlyphOrder()[2:]


for uni2 in online_uni_list:
    obj2 = online_font['glyf'][uni2]  # 獲取編碼uni2在online_font.ttf中對應的對象
    for uni1 in base_uni_list:
        obj1 = base_font['glyf'][uni1]  # 獲取編碼uni1在base_font.ttf 中對應的對象
        if obj1 == obj2:  # 判斷兩個對象是否相等
            dd = "&#x" + uni2[3:].lower() + ';'  # 修改爲Unicode編碼格式
            if dd in response:  # 如果編碼uni2的Unicode編碼格式 在response中,替換成origin_dict中的數字。
                response = response.replace(dd, origin_dict[uni1])

response的獲取採用的是request模塊

url = 'https://piaofang.maoyan.com/?ver=normal'
headers = {
    'User-Agent': '瀏覽器UA',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
}
response = requests.get(url=url, headers=headers).content  # 得到字節
charset = chardet.detect(response).get('encoding')  # 得到編碼格式
response = response.decode(charset, "ignore")  # 解碼得到字符串

運行結果展示

在這裏插入圖片描述
關注微信公衆賬號:非本科程序員,回覆0409獲取下載地址

在這裏插入圖片描述

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