🌈据说,看我文章时 关注、点赞、收藏 的 帅哥美女们 心情都会不自觉的好起来。
前言:
🧡作者简介:大家好我是 user_from_future ,意思是 “ 来自未来的用户 ” ,寓意着未来的自己一定很棒~
✨个人主页:点我直达,在这里肯定能找到你想要的~
👍专栏介绍:猿人学WEB题目专解 ,提供猿人学WEB题目总计20题的解题思路与方法,如有讲述错误,请不吝赐教。
想看往期历史文章,可以浏览此博文: 历史文章目录,后续所有文章发布都会同步更新此博文~

题目网址
题目详情

让我们找出 胜点最高 的召唤师的 姓名。
题目思路
这一题是字体加密题,所有胜点数据全都被不知名字符代替:

返回了这不知名字符的 value 和 woff 数据:

这 woff 自然是经过 base64 加密后的 .woff 文件字节。
我们 base64.b64decode 后,使用 fontTools.ttLib.TTFont 将 woff 数据转换成 xml 数据,再用 BeautifulSoup 的 xml 树解析:BeautifulSoup(open(f'q7_{index}.xml', 'r', encoding='utf-8').read(), 'xml').find('GlyphOrder').find_all('GlyphID')。
打开我们的 xml 文件,映入眼帘的是:

当我以为这题简简单单,打算直接解决他的时候,意外发生了:

可以很明显的看出来,相同数字的地方,解出来也是相同数字,但 0-9 的映射完全是乱的!
我就知道,这题没那么简单,再看 xml 文件,上面有一行小提示:<!-- The 'id' attribute is only for humans; it is ignored when parsed. --> 仅给人看,解析时忽略!
只能往下看:

这倒挺像是用描点来绘画数字的,我们获取到这里所有的信息看看:

把所有的 01 放在一个字符串里看看:

重新访问一次看看:

再重新访问一次看看:

有没有发现什么规律?
没错,值是固定的,我们可以根据值,看出他所代表的数字,有两种看法:
第一种选一次,对照 value 和真实的值,然后看出每个的对应关系。
第二种先执行一次下载 woff 文件,然后打开 在线解析woff文件 网站,上传我们的 woff 文件,即可知道映射关系:

总之,我们得到的映射字典是这样的:
PIXELS = {
'111': '',
'10100100100101010010010010': '0',
'1001101111': '1',
'100110101001010101011110101000': '2',
'10101100101000111100010101011010100101010100': '3',
'111111111111111': '4',
'1110101001001010110101010100101011111': '5',
'10101010100001010111010101101010010101000': '6',
'1111111': '7',
'101010101101010001010101101010101010010010010101001000010': '8',
'10010101001110101011010101010101000100100': '9'
}
这样处理之后,我们就得到了正确的数字:

接下来处理召唤师名称映射:

可以在此处看到名称对应的规则,然后就能得到每个召唤师名字对应的胜点数值:

解题源码
import base64
import requests
from io import BytesIO
from bs4 import BeautifulSoup
from fontTools.ttLib import TTFont
headers = {
'cookie': 'sessionid=eaqd1jn210tttc5l2xprh3e1zcizcvp4',
'User-Agent': 'yuanrenxue.project'
}
# 动态字体的映射
PIXELS = {
'111': '',
'10100100100101010010010010': '0',
'1001101111': '1',
'100110101001010101011110101000': '2',
'10101100101000111100010101011010100101010100': '3',
'111111111111111': '4',
'1110101001001010110101010100101011111': '5',
'10101010100001010111010101101010010101000': '6',
'1111111': '7',
'101010101101010001010101101010101010010010010101001000010': '8',
'10010101001110101011010101010101000100100': '9'
}
NAME = ['极镀ギ紬荕', '爷灬霸气傀儡', '梦战苍穹', '傲世哥', 'мaη肆風聲', '一刀メ隔世', '横刀メ绝杀', 'Q不死你R死你', '魔帝殤邪', '封刀不再战', '倾城孤狼', '戎马江湖', '狂得像风', '影之哀伤', '謸氕づ独尊', '傲视狂杀', '追风之梦', '枭雄在世', '傲视之巅', '黑夜刺客', '占你心为王', '爷来取你狗命', '御风踏血', '凫矢暮城', '孤影メ残刀', '野区霸王', '噬血啸月', '风逝无迹', '帅的睡不着', '血色杀戮者', '冷视天下', '帅出新高度', '風狆瑬蒗', '灵魂禁锢', 'ヤ地狱篮枫ゞ', '溅血メ破天', '剑尊メ杀戮', '塞外う飛龍', '哥‘K纯帅', '逆風祈雨', '恣意踏江山', '望断、天涯路', '地獄惡灵', '疯狂メ孽杀', '寂月灭影', '骚年霸称帝王', '狂杀メ无赦', '死灵的哀伤', '撩妹界扛把子', '霸刀☆藐视天下', '潇洒又能打', '狂卩龙灬巅丷峰', '羁旅天涯.', '南宫沐风', '风恋绝尘', '剑下孤魂', '一蓑烟雨', '领域★倾战', '威龙丶断魂神狙', '辉煌战绩', '屎来运赚', '伱、Bu够档次', '九音引魂箫', '骨子里的傲气', '霸海断长空', '没枪也很狂', '死魂★之灵']
values = {}
for index in range(1, 6):
data = requests.get(f'https://match.yuanrenxue.cn/api/match/7?page={index}', headers=headers).json()
# 使用文件保存字体
# open(f'q7_{index}.woff', 'wb').write(base64.b64decode(data['woff'].encode()))
# font = TTFont(f'q7_{index}.woff')
# font.saveXML(f'q7_{index}.xml')
# ids = BeautifulSoup(open(f'q7_{index}.xml', 'r', encoding='utf-8').read(), 'xml').find('glyf').find_all('TTGlyph') # .find('GlyphOrder').find_all('GlyphID')
# 使用内存保存字体
font_bytes = BytesIO(base64.b64decode(data['woff'].encode()))
font = TTFont(font_bytes)
font_bytes.close()
font_bytes = BytesIO()
font.saveXML(font_bytes)
ids = BeautifulSoup(font_bytes.getvalue(), 'xml').find('glyf').find_all('TTGlyph') # .find('GlyphOrder').find_all('GlyphID')
font_bytes.close()
# 映射数字关系
gid = {}
for g in ids:
gid[g['name']] = PIXELS[''.join(b['on'] for b in g.find_all('pt'))]
for i, d in enumerate(data['data']):
values[NAME[i + 1 + (index - 1) * 10]] = int(''.join(gid[dd.replace('&#x', 'uni')] for dd in d['value'].strip().split(' ')))
print(max(values, key=lambda v: values[v]))


被折叠的 条评论
为什么被折叠?



