【中等】 猿人学web第一届 第7题 动态字体,随风漂移

news2024/12/31 4:03:40

文章目录

  • 获取字体文件映射关系
  • 获取页面英雄排序
  • python 代码

这道题是 动态字体文件加密,找出动态字体文件中对应数字相同规律即可

数据接口 https://match.yuanrenxue.cn/api/match/7
数据接口没有加密值 cookie字段也没有
在这里插入图片描述

获取字体文件映射关系

多次观察 字体文件代表数字对应的 on 值是不变的
unia126 和 unic195 对应的数字都为 1,对应的 on 值都是相同的
在这里插入图片描述在这里插入图片描述
根据 数字对应的on值,编写一个映射字典

from fontTools.ttLib import TTFont  # pip install fontTools
from base64 import b64decode
from parsel import Selector  # pip install parsel


def demo(data):
    """data为接口返回的内容"""

    with open('7.ttf', mode='wb') as file:
        file.write(b64decode(data['woff']))  # 将 woff 字段 b64解码后写入到文件

    font = TTFont('7.ttf')  # 加载字体文件
    font.saveXML('7.xml')  # 保存为xml文件
    # 读取 xml 文件
    with open('7.xml', mode='r', encoding='utf-8') as f:
        xml_data = f.read()

    select = Selector(xml_data)
    glyf = select.css('glyf > TTGlyph')  # 获取 glyf 下所有的 TTglyph 标签
    for TTGlyph in glyf[1:]:  # 第 0 个标签的值是不需要的,所以从 第 1 个元素开始遍历
        name = TTGlyph.css('::attr(name)').get().replace('uni', '')  # 获取 TTGlyph 标签里对应的 name 属性,并将 uni 替换为空

        pt_tag = TTGlyph.css('pt')  # 获取 TTGlyph 下所有的 pt 标签
        on_list = []
        for pt in pt_tag:  # 遍历 pt 标签
            on = pt.css('::attr(on)').get()  # 获取 pt 标签里对应的 on 属性
            on_list.append(on)  # 将解析的到 on 属性值添加到列表中
        print(f"'{''.join(on_list)}': '{name}',")  # 打印出字典形式的字符串
        # ''.join(on_list) 对应字典键
        # name 对应字典值


if __name__ == '__main__':
    demo(# 这里放入接口返回的数据 copy 即可)

运行结果
在这里插入图片描述

再将对应编码替换成正确的数字即可
在这里插入图片描述

解析得到的映射字典 ↓

on_map = {
    '1001101111': '1',
    '101010101101010001010101101010101010010010010101001000010': '8',
    '10101010100001010111010101101010010101000': '6',
    '10100100100101010010010010': '0',
    '1110101001001010110101010100101011111': '5',
    '10010101001110101011010101010101000100100': '9',
    '100110101001010101011110101000': '2',
    '111111111111111': '4',
    '1111111': '7',
    '10101100101000111100010101011010100101010100': '3',
}

有了映射字典就可以请求并解析到正确的数字了

def save_font(font_data):
    on_map = {
        '1001101111': '1',
        '101010101101010001010101101010101010010010010101001000010': '8',
        '10101010100001010111010101101010010101000': '6',
        '10100100100101010010010010': '0',
        '1110101001001010110101010100101011111': '5',
        '10010101001110101011010101010101000100100': '9',
        '100110101001010101011110101000': '2',
        '111111111111111': '4',
        '1111111': '7',
        '10101100101000111100010101011010100101010100': '3',
    }

    with open('7.ttf', mode='wb') as f:
        f.write(b64decode(font_data['woff']))  # 保存字体文件

    font = TTFont('7.ttf')  # 加载字体文件
    font.saveXML('7.xml')  # 保存为xml文件

    # 读取 xml 文件
    with open('7.xml', mode='r', encoding='utf-8') as f:
        xml_data = f.read()

    select = Selector(xml_data)
    # 获取 <glyf> --> 所有 TTGlyph 标签
    TTGlyph = select.css('glyf > TTGlyph')[1:]  # 第 0 个标签的信息不需要,从第 1 个标签开始获取
    rep_dist = {}
    for tt in TTGlyph:
        name = tt.css('::attr(name)').get().replace('uni', '')  # TTGlyph标签 --> name 值
        pt = tt.css('pt')  # 获取 Glyph标签 --> TTGlyph标签 --> pt标签对应的 on 值
        on_list = []
        for pt_tag in pt:
            on_list.append(pt_tag.css('::attr(on)').get())
        rep_dist[name] = on_map[''.join(on_list)]  # 根据映射将 on 值替换成正确的数字

    result_dict = []
    for data in font_data['data']:
        num_list = []
        for nums in data['value'].replace('&#x', '').split(' ')[0:-1]:
            num_list.append(rep_dist[nums])
        result_dict.append(int(''.join(num_list)))
        #     print(rep_dist[nums], end='')
        # print()
    return result_dict

运行结果
在这里插入图片描述

获取页面英雄排序

每页英雄的排序是在 js 中做处理的, 在数据接口的 requests 栈
在这里插入图片描述

对应的 js 代码

let page = 1;
let name = ['极镀ギ紬荕', '爷灬霸气傀儡', '梦战苍穹', '傲世哥', 'мaη肆風聲', '一刀メ隔世', '横刀メ绝杀', 'Q不死你R死你', '魔帝殤邪', '封刀不再战', '倾城孤狼', '戎马江湖', '狂得像风', '影之哀伤', '謸氕づ独尊', '傲视狂杀', '追风之梦', '枭雄在世', '傲视之巅', '黑夜刺客', '占你心为王', '爷来取你狗命', '御风踏血', '凫矢暮城', '孤影メ残刀', '野区霸王', '噬血啸月', '风逝无迹', '帅的睡不着', '血色杀戮者', '冷视天下', '帅出新高度', '風狆瑬蒗', '灵魂禁锢', 'ヤ地狱篮枫ゞ', '溅血メ破天', '剑尊メ杀戮', '塞外う飛龍', '哥‘K纯帅', '逆風祈雨', '恣意踏江山', '望断、天涯路', '地獄惡灵', '疯狂メ孽杀', '寂月灭影', '骚年霸称帝王', '狂杀メ无赦', '死灵的哀伤', '撩妹界扛把子', '霸刀☆藐视天下', '潇洒又能打', '狂卩龙灬巅丷峰', '羁旅天涯.', '南宫沐风', '风恋绝尘', '剑下孤魂', '一蓑烟雨', '领域★倾战', '威龙丶断魂神狙', '辉煌战绩', '屎来运赚', '伱、Bu够档次', '九音引魂箫', '骨子里的傲气', '霸海断长空', '没枪也很狂', '死魂★之灵'];
let heroArray = []
for (let i = 0; i <= 4; i++) {
    let yyq = 1;
    // ['', '', '', '', '', '', '', '', '', ''] 对应一页十条数据
    ['', '', '', '', '', '', '', '', '', ''].forEach((index, val) => {
        // console.log(name[yyq + (page - 1) * 10]);
        heroArray.push(name[yyq + (page - 1) * 10])
        yyq += 1
    })
    page += 1;
}
console.log(heroArray)

运行结果
在这里插入图片描述

python 代码

import requests
from base64 import b64decode
from fontTools.ttLib import TTFont  # pip install fontTools
from parsel import Selector

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
}
cookies = {
    "sessionid": "你的SessionId"
}


def send_match6(page):
    url = "https://match.yuanrenxue.cn/api/match/7"
    params = {
        "page": f"{page}"
    }
    response = requests.get(url, headers=headers, cookies=cookies, params=params)
    return {
        'woff': response.json()['woff'],
        'data': response.json()['data']
    }


def save_font(font_data):
    on_map = {
        '1001101111': '1',
        '101010101101010001010101101010101010010010010101001000010': '8',
        '10101010100001010111010101101010010101000': '6',
        '10100100100101010010010010': '0',
        '1110101001001010110101010100101011111': '5',
        '10010101001110101011010101010101000100100': '9',
        '100110101001010101011110101000': '2',
        '111111111111111': '4',
        '1111111': '7',
        '10101100101000111100010101011010100101010100': '3',
    }

    with open('7.ttf', mode='wb') as f:
        f.write(b64decode(font_data['woff']))  # 保存字体文件

    font = TTFont('7.ttf')  # 加载字体文件
    font.saveXML('7.xml')  # 保存为xml文件

    # 读取 xml 文件
    with open('7.xml', mode='r', encoding='utf-8') as f:
        xml_data = f.read()

    select = Selector(xml_data)
    # 获取 <glyf> --> TTGlyph
    TTGlyph = select.css('glyf > TTGlyph')[1:]  # 第 0 个标签的信息不需要,从第 1 个标签开始获取
    rep_dist = {}
    for tt in TTGlyph:
        name = tt.css('::attr(name)').get().replace('uni', '')  # TTGlyph标签 --> name 值
        pt = tt.css('pt')  # 获取 Glyph标签 --> TTGlyph标签 --> pt标签对应的 on 值
        on_list = []
        for pt_tag in pt:
            on_list.append(pt_tag.css('::attr(on)').get())
        rep_dist[name] = on_map[''.join(on_list)]  # 根据映射将 on 值替换成正确的数字

    result_dict = []
    for data in font_data['data']:
        num_list = []
        for nums in data['value'].replace('&#x', '').split(' ')[0:-1]:
            num_list.append(rep_dist[nums])
        result_dict.append(int(''.join(num_list)))
        #     print(rep_dist[nums], end='')
        # print()
    return result_dict


if __name__ == '__main__':
    hero_array = [
        '爷灬霸气傀儡', '梦战苍穹', '傲世哥', 'мaη肆風聲', '一刀メ隔世', '横刀メ绝杀', 'Q不死你R死你', '魔帝殤邪', '封刀不再战', '倾城孤狼',
        '戎马江湖', '狂得像风', '影之哀伤', '謸氕づ独尊', '傲视狂杀', '追风之梦', '枭雄在世', '傲视之巅', '黑夜刺客', '占你心为王', 
        '爷来取你狗命', '御风踏血', '凫矢暮城', '孤影メ残刀', '野区霸王', '噬血啸月', '风逝无迹', '帅的睡不着', '血色杀戮者', '冷视天下',
        '帅出新高度', '風狆瑬蒗', '灵魂禁锢', 'ヤ地狱篮枫ゞ', '溅血メ破天', '剑尊メ杀戮', '塞外う飛龍', '哥‘K纯帅', '逆風祈雨', '恣意踏江山', 
        '望断、天涯路', '地獄惡灵', '疯狂メ孽杀', '寂月灭影', '骚年霸称帝王', '狂杀メ无赦', '死灵的哀伤', '撩妹界扛把子', '霸刀☆藐视天下', '潇洒又能打'
    ]  # 正确的英雄排序列表
    hero_nums = []  # 声明一个列表,用于存储所有的数值
    for page in range(1, 6):
        math6_data = send_match6(page)
        nums_list = save_font(math6_data)
        print(page, nums_list)  # 打印请求的页数,对应的列表(数值)
        for num in nums_list:  # 遍历每页得到的列表
            hero_nums.append(num)  # 将列表数值添加到 hreo_nums 列表中
    print(hero_nums)  # 打印所有页面的数值

    max_num = 0  # 定义一个变量,用于存储最大的数值
    for num in hero_nums:
        # 将 hero_nums 中的每一个数值与 max_num 作比较
        if num > max_num:  # 如果改数值比 max_num 大
            max_num = num  # max_num 就等于改数值

    hero_index = hero_nums.index(max_num)  # 获取列表中最大数值的索引
    print(hero_array[hero_index])  # 获取对应英雄列表的英雄名

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2046048.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.2 Oracle与SQL Server简介

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; 工&#x1f497;重&#x1f497;hao&#x1f497;&#xff1a;野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

仿Muduo库实现高并发服务器——事件监控Poller模块

Poller模块在整个项目的使用 下面代码是对I/O复用接口函数的基本使用。 回顾上篇文章&#xff1a;事件监控管理模块 这个模块是将触发事件的描述符&#xff0c;给到外面&#xff0c;让外面去做对应的处理。 #define MAX_EPOLLEVENTS 1024 class Poller {private:int _epfd;s…

三级_网络技术_18_路由器的配置及使用

1.在Cisco路由器上用于永久保存路由器的开机诊断程序、引导程序和操作系统软件的存储器是()。 Flash NVRAM RAM ROM 2.在Cisco路由器中主要用来永久保存路由器的开机诊断程序、引导程序和操作系统&#xff0c;以完成路由器初始化进程的存储器是()。 RAM Disk Flash RO…

Linux平台使用OPUS对Audio PCM数据进行编解码

1&#xff09;Audio编解码入门级小知识&#xff0c;分享给将要学习或者正在学习Audio编解码开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 Opus编码是一个开源的音频编码格式&#xff0c;具…

ArduPilot二次开发零基础教程

文章目录 前言一、概述二、开发环境搭建三、多旋翼MAVROS自主控制接口四、无人船&#xff08;车&#xff09;MAVROS自主控制接口五、二次开发基础六、控制LED灯七、自定义串口驱动八、Guided控制接口九、输出自定义PWM信号十、添加自定义MAVLINK消息和QGC通信十一、自定义日志十…

[MRCTF2020]套娃1

打开题目&#xff0c;查看源代码&#xff0c;有提示 有两层过滤 1.过滤"_"与"%5f" 。 这里要求的参数必须是"b_u_p_t"但是不能检测出"_"。这里看着很作弄人。其实这里要用到php里非法参数名的问题。可以参考一下博客 ?b.u.p.t2333…

探索Pandas的魔力:Python数据分析的终极武器

文章目录 探索Pandas的魔力&#xff1a;Python数据分析的终极武器背景&#xff1a;为何选择Pandas&#xff1f;引言&#xff1a;Pandas是什么&#xff1f;安装Pandas&#xff1a;一键安装的便捷基础函数&#xff1a;Pandas的五大法宝应用场景&#xff1a;Pandas的实战演练常见问…

浏览器调试工具-Chrome Dev Tools

浏览器调试模式下的各个调试工具是常用的工具集&#xff0c;能够帮助开发者理解、调试和优化网页。 1.打开方式 直接在浏览器中按下F12键右键点击页面上的任一元素&#xff0c;选择“检查”&#xff08;Inspect&#xff09;在浏览器右上角点击菜单按钮&#xff0c;选择“更多…

Redis:缓存击穿,缓存穿透,缓存雪崩

缓存穿透 缓存和数据库中都没有的数据&#xff0c;可用户还是源源不断的发起请求&#xff0c;导致每次请求都会到数据库&#xff0c;从而压垮数据库。 这将导致这个不存在的数据每次请求都要到存储层去查询&#xff0c;失去了缓存的意义。 *** 解决方案** 对空值进行缓存标…

音乐生成模型应用

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

根据年月计算当月有哪几个周,及每周的起止日期

示例 传参数年、月&#xff0c;返回包含当月的所有周数、及周的起止日期&#xff0c;支持跨月 特殊情况请自行修改函数 console.log(getWeeksInMonth(2024, 9));返回如下 源码 源码以elementUI的周选择框的起止日期作为参考 function getWeeksInMonth(year, month) {// 计…

讲透一个强大算法模型,Transformer !!零基础入门到精通,收藏这一篇就够了

哈喽&#xff0c;我是cos大壮&#xff01;~ **首先&#xff0c;官话&#xff1a;**Transformer 模型是由 Vaswani 等人在 2017 年提出的一种新型神经网络架构&#xff0c;用于解决序列到序列的任务&#xff0c;比如机器翻译、文本生成等。它的核心思想是通过「注意力机制」来捕…

冷知识:编程第一人是位伟大的女性

冷门智慧&#xff1a;阿达编程先驱的传奇人生揭秘在线播放免费听 - 喜马拉雅手机版欢迎收听由主播壹道徽为您带来的“冷门智慧&#xff1a;阿达编程先驱的传奇人生揭秘”精彩有声内容&#xff0c;该音频时长5分18秒&#xff0c;已被收听1062次&#xff0c;用户嘎嘎呗嘎嘎评价说…

关于msvcp120.dll丢失的解决方法的详细步骤教程,一步步教你修复丢失错误

msvcp120.dll是一个动态链接库文件&#xff08;DLL&#xff09;&#xff0c;它是 Microsoft Visual C 2013 Redistributable 的一部分。这个文件对于运行使用 C 编写的多种Windows应用程序非常重要。以下解析将分为几个部分来详细探讨此文件的来源、功能、重要性及其可能遇到的…

暑期全新测评《黑神话悟空》显卡测试与录屏工具推荐:性能优化与屏幕捕捉技巧

随着《黑神话悟空》这款备受期待的游戏即将问世&#xff0c;玩家们不仅对游戏的画质和性能充满好奇&#xff0c;更希望能够记录下游戏中的每一个精彩瞬间。本文将为您提供一份全面的指南&#xff0c;不仅包括《黑神话悟空》在主流显卡上的帧数测试结果&#xff0c;画质选项的优…

Windows Server 使用Docke部署挂载问题(安装后无限重启崩溃迁移镜像到D盘打包镜像)

文章目录 前言一、问题&#xff1a;无限重启崩溃尝试&#xff1a;权限不足&#xff1f;解决&#xff1a;用Docker-Compose安装并挂载数据卷 二、问题&#xff1a;镜像磁盘默认挂载在C盘尝试&#xff1a;通过修改Docker修改镜像磁盘到D盘解决&#xff1a;通过修改docker的settin…

【OpenCV】window 下 VS Code 配置OpenCV

文章目录 前言直接使用OpenCV 编译好的库自己编译OpenCVVS Code 安装MinGW下载下载Cmake编译OpenCV VS Code 运行cv程序VSCode配置运行CV程序 参考文章 前言 在网上找了些资料&#xff0c;大致得出VS Code开发OpenCV的环境配置流程&#xff0c;如下 安装VS Code安装MinGW安装…

详解 Python 中的面向对象编程(2)

引言 面向对象编程&#xff08;OOP&#xff09;是一种编程范式&#xff0c;它通过将属性和行为整合到对象中来构建程序。本教程将带你了解Python语言中面向对象编程的基本概念。 想象一下&#xff0c;对象就像是系统中的各个部件。可以把程序比作一条工厂流水线。在流水线的每一…

Spring Boot 的Web开发

Spring Boot 的Web开发 一、 静态资源映射规则 总结&#xff1a; 只要静态资源放在类路径下&#xff1a; called /static (or /public or /resources or /METAINF/resources 访问 &#xff1a; 当前项目根路径/ 静态资源名 二、 enjoy模板引擎 Enjoy模板引擎是一个轻量级的…

50ETF期权交易小技巧分享:期权的交易规律

今天带你了解50ETF期权交易小技巧分享&#xff1a;期权的交易规律。50ETF期权是一种以实物华夏上证50ETF基金为标的物的金融衍生品&#xff0c;它允许投资者在未来某个特定时间以特定价格买入或卖出一定数量的50ETF基金。 50ETF期权交易规律 1、短线思维&#xff0c;最长1周时…