猫眼电影字体破解(图片转码方法)

问题

        随便拿一篇电影做样例。我们发现猫眼的页面数据在预览窗口中全是小方框。在当我们拿到源码以后,数据全是加密后的。所以我们需要想办法破解加密,拿到数据。

破解过程 

        1.源码获取问题与破解

        分析

        在我们刚刚请求url的时候是可以得到数据的,但是过了一段时间后就无法获得数据。虽然状态码为200,但是却没有返回页面源码

一般这种应该是和时间戳有关系,在查看请求负载的时候我们发送,浏览器向这个url不仅发送了时间戳还有一个signKey的密钥。时间戳可以很容易得到,主要问题是如何获得signKey。

        全局搜索signKey,我们发现一段js代码,它的返回值就是我们请求负载的内容。所以需要想办法还原这段js代码。

        分析后发现:

  • d:获取当前时间的函数
  • r:随机数取整
  • c:内容如下method=GET&timeStamp=1725264890773&User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0&index=8&channelId=40011&sVersion=1
    • 可以发现就是多个信息进行拼接(时间戳+User-Agent+index+channelId+sVersion)。
  • f:固定为&key=A013F70DB97834C0A5492378BD76C53A

        分析图片如下:

        同时我们还发现signKey是通过MD5加密(c+f)后得到的。因为1经过MD5加密后得到的内容就是c4ca4238a0b923820dcc509a6f75849b,所以我们可以猜测(0,a[i(_0x140e("0xe4"))])('c+f')就是一个MD5的加密。

         js编写与调用

        有了以上分析后,我们就可以拿页面原始的js代码进行适当的改动。修改后的js代码如下,我们直接返回网页负载需要的params。

        添加首页cookie

        在完成上面步骤后,我们调用js,虽然得到了params,但是还是无法获得到页面的源代码,这可能和cookie有关系,所以我们创建一个session,通过访问首页来保存首页的cookie,然后再来访问这个url看看结果。

        我们发现浏览器请求了两次https://www.maoyan.com/,且第一次存在302跳转,跳转到https://www.maoyan.com/,所以是请求了两次。在python代码中,我们只需要请求有302跳转的链接即可,因为程序会自动进行第二次跳转。

        添加cookie后,使用python程序调用js代码返回params,使用js生成的params去访问url地址运行结果如下:

        2.字体破解

        字体图片下载

        在拿到页面源码以后,我们需要对数字进行获取。直接在返回的源码中搜索,获取.woff文件。得到url://s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/e3dfe524.woff,因为每一次请求得到的源码中,woff文件的链接都不同,所以我们需要使用数据提取手段,提取每一次请求得到的woff文件链接并下载保存下来。

        下载并保存woff文件,使用python代码识别woff文件,并保存为图片,识别代码如下,之后会整合到源码中:

from fontTools.ttLib import TTFont
from reportlab.graphics.shapes import Drawing, Path, Group
from reportlab.graphics import renderPM
from reportlab.lib import colors
from reportlab.graphics.shapes import Pathclass ReportLabPen(BasePen):def __init__(self, glyphSet, path=None):BasePen.__init__(self, glyphSet)if path is None:path = Path()self.path = pathdef _moveTo(self, p):(x, y) = pself.path.moveTo(x, y)def _lineTo(self, p):(x, y) = pself.path.lineTo(x, y)def _curveToOne(self, p1, p2, p3):(x1, y1) = p1(x2, y2) = p2(x3, y3) = p3self.path.curveTo(x1, y1, x2, y2, x3, y3)def closePath(self):self.path.closePath()def ttfToImage(fontName, imagePath, fmt="png"):font = TTFont(fontName)  # 打开 WOFF 字体文件gs = font.getGlyphSet()glyphNames = font.getGlyphNames()[1:]  # 排除第一个 .notdef 字形for i in glyphNames:g = gs[i]  # 获取当前字形的 Glyph 对象pen = ReportLabPen(gs, Path(fillcolor=colors.red, strokeWidth=1))  # 创建 ReportLabPen 对象,并设置相关参数g.draw(pen)  # 将当前字形通过 pen 绘制到 path 对象上# 字形的宽度和高度w, h = g.width, g.width + 300  g = Group(pen.path)g.translate(0, 100)  # 将图形向下移动 100 个像素d = Drawing(w, h)  # 创建 Drawing 对象,设置宽度和高度d.add(g)  # 将 Group 对象添加到 Drawing 对象中# 定义输出图片路径和文件名imageFile = f"{imagePath}/{i}.{fmt}"# 将 Drawing 对象渲染成图像文件并保存renderPM.drawToFile(d, imageFile, fmt)# 示例用法:将 `mao.woff` 字体文件的字形保存为图像
ttfToImage(fontName="mao.woff", imagePath='images')

        识别结果如下:

         识别图片

        识别代码如下,之后会整合到源码中:

import os
import ddddocr  # 导入 ddddocr 库def orc():# 创建一个 ddddocr 的 OCR 对象ocr = ddddocr.DdddOcr()dicts = {}  # 初始化一个空字典,用于存储识别结果lists = os.listdir('./images')  # 获取 images 目录下的所有文件列表# 遍历每个图片文件for imgs in lists:# 以二进制模式读取图片文件with open('./images/' + imgs, 'rb') as f:img_bytes = f.read()# 使用 OCR 对象的 classification 方法识别图片内容res = ocr.classification(img_bytes)# 输出文件名中提取的 Unicode 代码print(222222222222222222, imgs[3:-4])try:# 将文件名中的 Unicode 代码转换为字符,并将识别结果存入字典dicts[eval('u\'\\u' + imgs[3:-4].lower() + '\'')] = resexcept:# 如果转换或存储过程中出错,则跳过pass# 打印当前的字典内容print(dicts)# 调用 orc 函数
orc()

        字典输出结果如下:

字典替换

        拿到页面加密的源码,然后根据字典的key来替换掉对应的数字

        替换后的数字与原始页面一样

源码

        py文件

import requests
import execjs
import re
import shutil
import os
import ddddocr
from fontTools.pens.basePen import BasePen
from fontTools.ttLib import TTFont
from reportlab.graphics.shapes import Drawing, Path, Group
from reportlab.graphics import renderPM
from reportlab.lib import colors
from reportlab.graphics.shapes import Pathclass ReportLabPen(BasePen):def __init__(self, glyphSet, path=None):BasePen.__init__(self, glyphSet)if path is None:path = Path()self.path = pathdef _moveTo(self, p):(x, y) = pself.path.moveTo(x, y)def _lineTo(self, p):(x, y) = pself.path.lineTo(x, y)def _curveToOne(self, p1, p2, p3):(x1, y1) = p1(x2, y2) = p2(x3, y3) = p3self.path.curveTo(x1, y1, x2, y2, x3, y3)def closePath(self):self.path.closePath()def ttfToImage(fontName, imagePath, fmt="png"):font = TTFont(fontName)  # 打开 WOFF 字体文件gs = font.getGlyphSet()glyphNames = font.getGlyphNames()[1:]  # 排除第一个 .notdef 字形for i in glyphNames:g = gs[i]  # 获取当前字形的 Glyph 对象pen = ReportLabPen(gs, Path(fillcolor=colors.red, strokeWidth=1))  # 创建 ReportLabPen 对象,并设置相关参数g.draw(pen)  # 将当前字形通过 pen 绘制到 path 对象上# 字形的宽度和高度w, h = g.width, g.width + 300g = Group(pen.path)g.translate(0, 100)  # 将图形向下移动 100 个像素d = Drawing(w, h)  # 创建 Drawing 对象,设置宽度和高度d.add(g)  # 将 Group 对象添加到 Drawing 对象中# 定义输出图片路径和文件名imageFile = f"{imagePath}/{i}.{fmt}"# 将 Drawing 对象渲染成图像文件并保存renderPM.drawToFile(d, imageFile, fmt)def download_woff():with open('猫眼.js','r',encoding='utf-8') as f:ctx = execjs.compile(f.read())headers_home = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6","Cache-Control": "max-age=0","Connection": "keep-alive","Sec-Fetch-Dest": "document","Sec-Fetch-Mode": "navigate","Sec-Fetch-Site": "none","Sec-Fetch-User": "?1","Upgrade-Insecure-Requests": "1","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0","sec-ch-ua": "\"Chromium\";v=\"128\", \"Not;A=Brand\";v=\"24\", \"Microsoft Edge\";v=\"128\"","sec-ch-ua-mobile": "?0","sec-ch-ua-platform": "\"Windows\""}cookies_home = {"_lxsdk_s": "191b2c23b90-602-526-0ba%7C%7C1"}url = "https://www.maoyan.com/"s = requests.session()# 访问首页,保存cookier = s.get(url, headers=headers_home, cookies=cookies_home)headers = {"Accept": "*/*","Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6","Connection": "keep-alive","Referer": "https://www.maoyan.com/films/1464004","Sec-Fetch-Dest": "empty","Sec-Fetch-Mode": "cors","Sec-Fetch-Site": "same-origin","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0","X-Requested-With": "XMLHttpRequest","sec-ch-ua": "\"Chromium\";v=\"128\", \"Not;A=Brand\";v=\"24\", \"Microsoft Edge\";v=\"128\"","sec-ch-ua-mobile": "?0","sec-ch-ua-platform": "\"Windows\""}url = "https://www.maoyan.com/ajax/films/1464004"params = ctx.call("get_params")response = s.get(url, headers=headers, params=params).text# 保存woffwoff_url = "https:" + re.findall(r',url.*?woff', response)[0].split('"')[1]woff_res = s.get(woff_url).contentwith open('mao.woff', 'wb') as f:f.write(woff_res)f.close()result = re.findall('<span class="stonefont">(.*?)</span>', response)return resultdef clear_folder(folder_path):# 确保指定路径是一个文件夹if os.path.isdir(folder_path):# 遍历文件夹中的所有文件和子文件夹for filename in os.listdir(folder_path):file_path = os.path.join(folder_path, filename)try:# 如果是文件则删除if os.path.isfile(file_path) or os.path.islink(file_path):os.unlink(file_path)# 如果是文件夹则删除整个文件夹elif os.path.isdir(file_path):shutil.rmtree(file_path)except Exception as e:print(f"删除 {file_path} 时出错: {e}")print("删除完成")def orc():# 创建一个 ddddocr 的 OCR 对象ocr = ddddocr.DdddOcr()dicts = {}  # 初始化一个空字典,用于存储识别结果lists = os.listdir('./images')  # 获取 images 目录下的所有文件列表# 遍历每个图片文件for imgs in lists:# 以二进制模式读取图片文件with open('./images/' + imgs, 'rb') as f:img_bytes = f.read()# 使用 OCR 对象的 classification 方法识别图片内容res = ocr.classification(img_bytes)# 输出文件名中提取的 Unicode 代码print(222222222222222222, imgs[3:-4])try:# 将文件名中的 Unicode 代码转换为字符,并将识别结果存入字典dicts[eval('u\'\\u' + imgs[3:-4].lower() + '\'')] = resexcept:# 如果转换或存储过程中出错,则跳过pass# 返回字典内容return dictsif __name__ == '__main__':data = download_woff()# 指定要清空的文件夹路径folder_path = './images'clear_folder(folder_path)# 转换 TTF 字体并将字形转换为 PNG 图片ttfToImage(fontName="mao.woff", imagePath='images')# 使用ocr识别图片,返回字典res = orc()print(data)print(res)# 遍历字典并将识别结果输出for i in data:# 首先去掉所有的 &#x 和 ;cleaned_str = i.replace('&#x', '').replace(';', '')# 然后进行字符替换for key, value in res.items():cleaned_str = cleaned_str.replace(key.encode('unicode_escape').decode('ascii').replace('\\u', ''), value)print(cleaned_str)

        js文件

const CryptoJS = require('crypto-js')var r = Math["ceil"](10 * Math["random"]())
var d = (new Date)["getTime"]()
var c = "method=GET&timeStamp="+d+'&User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0&index='+r+'&channelId=40011&sVersion=1'
var f = "&key=A013F70DB97834C0A5492378BD76C53A"function get_params(){return{"timeStamp": d,"index": r,"signKey": CryptoJS.MD5(c+f).toString(),"channelId": "40011","sVersion": "1","webdriver": "false"}
}

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

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

相关文章

【MySQL】MySQL操作介绍

MySQL操作 认识 MySQL什么是 MySQL关系型数据库的组成结构"客户端-服务器"结构 数据库的基本操作创建数据库查看数据库删除数据库使用数据库 数据类型整型浮点类型字符串类型日期类型总结 表的操作创建表查看表查看表的信息删除表 数据的基础操作插入数据指定列插入全…

Java过滤器和监听器

1. 过滤器 1.1. 过滤器 使用baseServlet的优点&#xff1a;方便进行乱码的统一处理&#xff0c;但是如果不使用servlet&#xff0c;在进行中文乱码处理时就需要在每个servlet中书写&#xff0c;比较麻烦 问题&#xff1a;重复的代码在项目中多次使用书写 解决&#xff1a;过滤…

2024 第七届“巅峰极客”网络安全技能挑战赛初赛 Web方向 题解WirteUp

EncirclingGame 题目描述&#xff1a;A simple game, enjoy it and get the flag when you complete it. 开题&#xff0c;前端小游戏&#xff0c;红点出不去就行 直接玩通关了 看看如何不玩也能拿到flag&#xff0c;flag存储在后端php文件内&#xff0c;前端找不到。 看一下…

【原创】java+springboot+mysql校园二手商品交易网设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

【MySQL】MySQL基础

目录 什么是数据库主流数据库基本使用MySQL的安装连接服务器服务器、数据库、表关系使用案例数据逻辑存储 MySQL的架构SQL分类什么是存储引擎 什么是数据库 mysql它是数据库服务的客户端mysqld它是数据库服务的服务器端mysql本质&#xff1a;基于C&#xff08;mysql&#xff09…

QT 编译报错:C3861: ‘tr‘ identifier not found

问题&#xff1a; QT 编译报错&#xff1a;C3861&#xff1a; ‘tr’ identifier not found 原因 使用tr的地方所在的类没有继承自 QObject 类 或者在不在某一类中&#xff0c; 解决方案 就直接用类名引用 &#xff1a;QObject::tr( )

【舍入,取整,取小数,取余数丨Excel 函数】

数学函数 1、Round函数 Roundup函数 Rounddown函数 取整&#xff1a;(Int /Trunc)其他舍入函数&#xff1a; 2、Mod函数用Mod函数提取小数用Mod函数 分奇偶通过身份证号码判断性别 1、Round函数 Roundup函数 Rounddown函数 Round(数字&#xff0c;保留几位小数)&#xff08;四…

SOEX从去中心化的链上社交关系到创收策略

是时候摆脱传统的在线社区&#xff0c;真正进入 Web3 了&#xff0c;利用区块链的力量&#xff0c;并理解社交互动的意义远不止分享内容或复制交易。代币化将赋能参与提升到一个全新的水平&#xff0c;并带来一系列新的机会。 社交网络可以发挥强大的作用&#xff0c;尤其是从…

Android的logcat日志详解

Android log系统 logcat介绍 logcat是android中的一个命令行工具&#xff0c;可以用于得到程序的log信息。下面介绍 adb logcat中的详细参数命令以及如何才能高效的打印日志&#xff0c;或把日志保存到我们指定的位置。 可以输入 adb logcat --help&#xff0c;查看一下一些简…

VMware vSphere5.0关闭虚拟机电源时,报错从ESXI主机接收到错误

ESXI和VCENTER都是5.0版本的&#xff0c;有台虚拟机关机报错提示从ESXI主机接受到意外错误 具体报错信息如下&#xff1a; 从VCENTER平台对该虚拟机做任何操作都无法生效&#xff0c;后来查看了虚拟机的网络和端口&#xff0c;发现SSH能正常联通&#xff0c;进入虚拟机后使用命…

【云原生】docker 部署 Doris 数据库使用详解

目录 一、前言 二、数据分析概述 2.1 什么是数据分析 2.2 数据分析目的和意义 2.3 数据分析常用的技术和工具 2.3.1 编程语言 2.3.2 数据处理和分析库 2.3.3 数据可视化工具 2.3.4 数据库系统 2.3.5大数据处理框架 2.3.6 云服务和平台 2.3.7 其他工具 三、Doris介绍…

gdb中使用python脚本

1、入门案例 首先有1个a.cpp&#xff0c;代码如下&#xff1a; #include <map> #include <set> #include <iostream> #include <string>using namespace std;struct MyStruct {std::string mName;std::map<int, std::string> mField1;std::set…

51单片机的无线病床呼叫系统【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块温湿度传感器模块矩阵按键时钟模块等模块构成。适用于病床呼叫系统、16床位呼叫等相似项目。 可实现基本功能: 1、LCD1602实时显示北京时间、温湿度信息、呼叫床位等信息&#xff1b; 2、DHT11采集病房温湿度信息&…

深度学习的发展历程

深度学习的起源 在机器学习中&#xff0c;我们经常使用两种方式来表示特征&#xff1a;局部表示&#xff08;Local Representation&#xff09;和分布式表示&#xff08;Distributed Representation&#xff09;。以颜色表示为例&#xff0c;见下图&#xff1a; 要学习到一种好…

iPhone手机清理软件:照片清理功能全解析

在数字化生活中&#xff0c;智能手机成为我们记录生活点滴的主要工具&#xff0c;尤其是iPhone&#xff0c;以其卓越的相机功能备受用户青睐。然而&#xff0c;成千上万的照片迅速堆积&#xff0c;不仅占用了大量存储空间&#xff0c;还使得设备运行缓慢。在众多解决方案中&…

【数据分享】《中国城市统计年鉴》(1985-2023)全PDF版本 第一次补档

数据介绍 中国城市&#xff0c;如同一本生动的历史书&#xff0c;承载着经济、社会的快速变迁。《中国城市统计年鉴》记录了城市的发展轨迹&#xff0c;是我们理解城市化进程、洞察城市挑战的重要指南。 这份年鉴的数据庞大而详实&#xff0c;囊括了中国城市发展的多个方面。…

船舶机械设备5G智能工厂物联数字孪生平台,推进制造业数字化转型

船舶机械设备5G智能工厂物联数字孪生平台&#xff0c;推进制造业数字化转型。在当今数字化浪潮推动下&#xff0c;船舶制造业正经历着前所未有的变革。为了应对市场的快速变化&#xff0c;提升生产效率&#xff0c;降低成本&#xff0c;并增强国际竞争力&#xff0c;船舶机械设…

海底生物检测-目标检测数据集(包括VOC格式、YOLO格式)

海底生物检测-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Kp4Reqt4tq1IafVF33IrnA?pwddxbv 提取码&#xff1a;dxbv 数据集信息介绍&#xff1a; 共有 7383 张图像和一一对应的标注文件 标…

仕考网:事业编考试考什么?

事业编考试科目为&#xff1a; 《职测》《综应》《公基》三选二 事业编有哪些招考形式? ①联考 多省份统一考试&#xff0c;考试时间、考试内容相同&#xff0c;每年两次&#xff0c;上半年5月和下半年10月各一次; ②单招 用人单位单独招聘&#xff0c;考试时间和内容自…

js原型与原型链详解(万文总结,一文搞懂原型链!)

目录 一&#xff0c;原型 1&#xff0c; 对象 2&#xff0c;原型&#xff08;原型对象&#xff09; 二&#xff0c;隐式原型__proto__ 1&#xff0c;__proto__ 2&#xff0c;考你一下 三&#xff0c;原型链 1&#xff0c;Object.prototype 2&#xff0c;链 四&#xff0c;练…