
字体反爬: 调用自定义的ttf文件来渲染网页中的文字,使得 源码和网页中的内容不一致,而是相应的字体编码, 从而无法通过在源码拿到真正的值
目标地址:http://glidedsky.com/level/web/crawler-font-puzzle-1

打开google调试工具检查发现网页上和源码之中的数字不一样, 已经确认该题目为 字体反扒 直接进入正题:

获取字体文件:
1丶直接找到数字节点属性:style 的 font-family 的值:glided_sky,在源码中找到 引入的的字体文件 并保存下来到本地


2丶该字体文件通过base64编码保存的 直接请求 将编码的值 和 节点中的数字内容 获取到 (获取的方式自己选择合适的即可,本文使用 pyquery 模块进行操作 )
import base64import requestsfrom pyquery import PyQuery as pyqresponse = requests.get(f'http://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 TTFontdef 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)
将获取的值传入这个方法就能获取得到网页上的正确数值了

!!!搞定!!! 将剩下的 999 页的值 统计出来 求和 就得到了正确答案
本项目的所有代码和相关文章, 仅用于经验技术交流分享,禁止将相关技术应用到不正当途径,因为滥用技术产生的风险与本人无关。