python爬蟲—字體反爬
目標地址://glidedsky.com/level/web/crawler-font-puzzle-1
打開google調試工具檢查發現網頁上和源碼之中的數字不一樣, 已經確認該題目為 字體反扒 直接進入正題:
獲取字體文件:
1丶直接找到數位元組點屬性:style 的 font-family 的值:glided_sky,在源碼中找到 引入的的字體文件 並保存下來到本地
2丶該字體文件通過base64編碼保存的 直接請求 將編碼的值 和 節點中的數字內容 獲取到 (獲取的方式自己選擇合適的即可,本文使用 pyquery 模組進行操作 )
import base64
import requests
from pyquery import PyQuery as pyq
response = requests.get(f'//glidedsky.com/level/web/crawler-font-puzzle-1?page=1', headers=headers, cookies=cookies,verify=False)
doc = pyq(response.text)
cts = doc('style')
base_info = ''.join([ pyq(i).text().split('base64,')[1].split(')')[0] for i in cts])
cts = doc('.col-md-1')
num_list = ([pyq(i).text() for i in cts])
print(f' num_list {num_list}')
3丶將獲取得到的base64值保存為本地 .ttf 並將 源碼中的數值進行匹配 得到網頁上展示的真正值
將保存的字體文件使用 字體編輯器 打開並手動確認編碼和數字之間的對應關係
具體實現程式碼如下
# 字體轉換
from fontTools.ttLib import TTFont
def font_switch(base_info, number_info):
page_one = base_info
b=base64.b64decode(page_one)
with open('new_page.ttf','wb')as f:
f.write(b)
font=TTFont('main.ttf') # 提前保存的一份本地文件 打開本地字體文件local.ttf
# font.saveXML('main.xml') #將ttf文件轉化成xml格式並保存到本地,主要是方便我們查看內部數據結構
obj_list1=font.getGlyphNames()[1:] #獲取所有字元的對象,去除第一個
uni_list1=font.getGlyphOrder()[1:] #獲取所有編碼,去除前1個
print(f' uni_list1 {uni_list1}')
# 手動確認編碼和數字之間的對應關係,保存到字典中
dict={
'seven':6,
'six':8,
'four':0,
'eight':5,
'two':1,
'five':4,
'one':9,
'zero':7,
'nine':2,
'three':3,
}
# 網頁新下載的
font2=TTFont('new_page.ttf') # 打開新下載的字體文件
obj_list2=font2.getGlyphNames()[1:] #獲取所有字元的對象,去除第一個
uni_list2=font2.getGlyphOrder()[1:] #獲取所有編碼,去除前1個
new_dict= {}
for uni2 in uni_list2:
print(f'uni2 : {uni2}')
obj2=font2['glyf'][uni2] #獲取編碼uni2在new_page.ttf中對應的對象
for uni1 in uni_list1:
obj1=font['glyf'][uni1]
if obj1==obj2:
new_dict[f'{uni2}'] = dict[uni1]
# 得到字體轉化後的真正值
print(f' new_dict {new_dict}')
#TODO 將傳進來的數字轉化
number = number_info
# 列表
lists = [
'zero',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
]
new_number = [int(''.join([str(new_dict[lists[int(n)]]) for n in num])) for num in number]
return sum(new_number)