本人呢很喜欢爬虫,但是技术不好,所以呢就一直慢慢的摸索着,也不知道那什么练手进行学习,直到我在偶然的机会接触到了猿人学,发现了 猿人学web端爬虫攻防平台这个网站,久旱逢甘霖,他乡遇故知呀(蹩脚的词语)也让我的爬虫技术有了很大的提升,今天呢我就说一下第七题,字体反爬(其他的题目我也有做,有时间也都会发表一下思路)
- 爬取的网站
猿人学web端爬虫攻防平台第七题动态字体
- 查看数据来源和加密方式
这就很方便了,数据和字体文件都在一起, - 多次请求观察字体文件,可以看出文字都是一样的,只是顺序不一样,对应的name也不一样,所以是动态字体
通过观察同一个字的字形数据,发现on值都是一样的
- 使用相同的数据进行构造映射
base_font={'font':[
{'name':'ꢕ','value':'4','hex':'ec9467393c47041e0fafff7f4a2852a8'},
{'name':'덁','value':'9','hex':'4119e3dc64f73251d40cf1fc0323e20f'},
{'name':'뙃','value':'6','hex':'af603543300bfc5f0e35e941d4208759'},
{'name':'뤗','value':'2','hex':'9bb92485b3e2ba4bd8a93ebbd3a0fa4e'},
{'name':'숖','value':'0','hex':'0aef9a3385d96e7bdd1f3003669a940c'},
{'name':'쎇','value':'3','hex':'b024173b00a3c901b6e696ba12812124'},
{'name':'옷','value':'7','hex':'3dcfec8e26ef48730f25363da55da77a'},
{'name':'','value':'1','hex':'2c0ec07331fa25dc226f1ca83561cb46'},
{'name':'','value':'5','hex':'9ebca885e21990cee127d23d03acb3ac'},
{'name':'','value':'8','hex':'f9d12372b7002b9a1522dd3dd142cf70'},
]}
- 每次请求都循环字体文件中的每个字的字形和提前做好的映射做比对,然后在源网页中进行替换
代码如下(对爬虫有兴趣的小伙伴,也可以做一下猿人学的题,还有glidedshy,scrape center等平台的题目,都很有营养) 个人建议,不喜勿喷
import re
import requests
import base64
from hashlib import md5
import json
from fontTools.ttLib import TTFont
headers = {"User-Agent": "yuanrenxue.project", }
url= 'http://match.yuanrenxue.com/api/match/7'
ret = requests.get(url,headers=headers)
ret_str = ret.text
wof = base64.b64decode(ret.json()['woff'])
with open('猿人学7.woff','wb') as f:
f.write(wof)
font = TTFont('猿人学7.woff')
font.saveXML('猿人学7.xml')
base_font={'font':[
{'name':'ꢕ','value':'4','hex':'ec9467393c47041e0fafff7f4a2852a8'},
{'name':'덁','value':'9','hex':'4119e3dc64f73251d40cf1fc0323e20f'},
{'name':'뙃','value':'6','hex':'af603543300bfc5f0e35e941d4208759'},
{'name':'뤗','value':'2','hex':'9bb92485b3e2ba4bd8a93ebbd3a0fa4e'},
{'name':'숖','value':'0','hex':'0aef9a3385d96e7bdd1f3003669a940c'},
{'name':'쎇','value':'3','hex':'b024173b00a3c901b6e696ba12812124'},
{'name':'옷','value':'7','hex':'3dcfec8e26ef48730f25363da55da77a'},
{'name':'','value':'1','hex':'2c0ec07331fa25dc226f1ca83561cb46'},
{'name':'','value':'5','hex':'9ebca885e21990cee127d23d03acb3ac'},
{'name':'','value':'8','hex':'f9d12372b7002b9a1522dd3dd142cf70'},
]}
# print(font.getGlyphOrder())
# for i in base_font['font']:
# # print('uni'+i['name'][3:-1].zfill(4))0
# font_cmap = font['glyf'].glyphs['uni'+i['name'][3:-1]].flags
# # print(font_cmap)
# font_cmap_hex = md5(font_cmap).hexdigest()
# print(i['name'],font_cmap_hex)
uni_list = font.getGlyphOrder()
uni_list.remove('.notdef')
for i in uni_list:
font_cmap = font['glyf'].glyphs[i].flags
font_cmap_hex = md5(font_cmap).hexdigest()
for j in base_font['font']:
if font_cmap_hex==j['hex']:
ret_str = ret_str.replace(i.replace('uni','&#x'),j['value'])
print(ret_str)
k = json.loads(ret_str)['data']
print(k)