当前位置: 首页> 房产> 建筑 > 合肥卫来_静态网站开发步骤_可以推广赚钱的软件_seo网站优化培训怎么样

合肥卫来_静态网站开发步骤_可以推广赚钱的软件_seo网站优化培训怎么样

时间:2025/7/15 15:02:07来源:https://blog.csdn.net/qq_41806966/article/details/146297881 浏览次数:0次
合肥卫来_静态网站开发步骤_可以推广赚钱的软件_seo网站优化培训怎么样

Hi I’m Shendi

最近有小程序爬虫需求,于是在这里简略记录下来经过


记一次小程序爬虫(反编译-自动化字体映射生成)



方案

爬取数据的办法通常有几种,一种是自动化脚本。即模拟用户操作,在移动设备上可以通过无障碍来获取元素数据,另一种是通过接口获取数据。


通过监听移动设备数据(中间人)

能直接通过接口爬取数据是最好的,所以最开始使用的就是监听数据的形式

具体流程就是在移动设备设置代理,让数据经过电脑的代理服务器,并在移动设备安装证书,这样就可以监听到数据了

不过这个方法尝试失败了,因为在Android9以后,用户证书不再被信任,而要安装系统证书需要Root…尝试一番太过麻烦就放弃了。



通过无障碍抓取数据

本着可见皆可爬的原则,觉得无障碍爬取一定是没有问题,所以在稍微尝试了一番后,编写了无障碍APP爬取,果然是可以爬的,然后我就开始编写后续所有的代码…

其中有图片爬取,不过没关系,可以自动化操作,点击图片,长按保存让其进入相册,然后在相册中读取最新的图片就可以了。并且小程序保存会自动输出保存的图片路径,也可以通过无障碍获取这个地址进行操作。

等我编写完,我发现,有一个数据是乱的(正常的文字,但是连起来狗屁不通,与界面上显示的不一致),我开始仔细分析哪里的问题…思索无果放弃了。

现在对于要完成这个目标的选择有:

  • 尝试反编译小程序源码
  • 直接通过OCR读取屏幕转文字,配合无障碍完成整个爬取,这是没有任何办法时的最后的办法


反编译小程序代码

但总是要爬的,所以开始反编译,因为微信可以电脑上打开小程序,所以反编译简单了起来,只要使用工具就可以了,反编译成功了,获取到了小程序源码。

反编译过程可以看这个:https://blog.csdn.net/weixin_54261528/article/details/145663372


反编译后,我又想到是否可以直接在电脑上监听接口数据,因为小程序是电脑微信打开的,我使用mitmproxy监听,的确监听到了,这样token就可以拿到了。

不过其中的一些关键数据是加密的,正好有源码,查看源码,一个个寻找…

最终,这个小程序使用RSA加密了数据,私钥都在小程序代码中,所以我很容易解密了。接口包含timestamp,token,random,sign,这四个关键参数,根据源代码显示的,将前三个字符串拼接,通过md5生成的sign就可以通过接口验证了。


现在一切都通了,好像很顺利,但是我解密的数据是HTML实体编码的,我解码后发现,跟无障碍遇到的情况一样,跟显示的文字完全对不上!我仔细查找源代码,以为有什么地方漏看了,少了一个解码步骤…

除了一个加载自定义字体的操作,没有任何东西了,所以,是不是字体的问题?了解后,果然,字体反爬是一种常见的手段,但是如何用字体将实体编码解析成文本?这可就头疼了。


自定义字体的自动化映射获取

最后的问题就是处理掉这个字体的问题,整个爬取就大功告成了

我通过源代码,下载了自定义的字体文件,这个字体可以理解为一个编码对应一个图片…所以,能想到的就是编写一个映射,将编码与正确文字对应…但手动编写也太浪费时间了,并且如果字很多呢?

字体在线编辑可以用这个看字体编码与字体对应:https://kekee000.github.io/fonteditor/


所以我第一时间想到,能不能使用OCR识别来全自动生成映射?只要把字体分割成一个个的,然后一个个识别就可以了…于是编写了以下代码(Python)

import io
import os
import ddddocr
from PIL import ImageDraw, ImageFont, Image
from fontTools.ttLib import TTFont# 将字体文件生成映射的python代码,通过ocr自动识别。
class UniversalFontRecognition(object):def __init__(self, font_path):self.font_path = font_pathself.ocr = ddddocr.DdddOcr(show_ad=False)def font_to_xml(self, xml_path=None):"""将 TTF 字体文件转换为 XML 格式"""if not xml_path:filename_with_ext = os.path.basename(self.font_path)filename_only = os.path.splitext(filename_with_ext)[0]xml_path = f'{filename_only}.xml'font = TTFont(self.font_path)font.saveXML(xml_path)def font_to_img(self, char_list, img_size=100, font_ratio=0.7):"""将字体字符渲染成图片,并使用 OCR 识别"""normal_dict = {}for char in char_list:char_code = chr(char)  # 直接转换 Unicodeimg = Image.new('RGB', (img_size, img_size), (255, 255, 255))  # 修正背景色draw = ImageDraw.Draw(img)font = ImageFont.truetype(self.font_path, int(img_size * font_ratio))# 获取文本边界bbox = draw.textbbox((0, 0), char_code, font=font)if bbox is None:continue  # 跳过无法获取尺寸的字符x, y = bbox[2] - bbox[0], bbox[3] - bbox[1]  # 计算宽高draw.text(((img_size - x) // 2, (img_size - y) // 2), char_code, font=font, fill=(0, 0, 0))# 将图片保存为字节流img_bytes = io.BytesIO()img.save(img_bytes, format='JPEG')image_bytes = img_bytes.getvalue()# 使用 OCR 识别word = self.ocr.classification(image_bytes)normal_dict[char] = word[0] if word and len(word) > 0 else ''return normal_dictdef crack(self):"""解析 TTF 字体文件并生成 Unicode → 真实字符的映射"""with open(self.font_path, 'rb') as fr:font_bytes = fr.read()with TTFont(io.BytesIO(font_bytes)) as font_parse:u_d = font_parse.getBestCmap()  # 获取 Unicode → 字体编码的映射return self.font_to_img(list(u_d.keys()))# === 使用示例 ===
ufr = UniversalFontRecognition(r"font/sfont.ttf")# 1. 可选:导出 XML,查看字体编码信息
ufr.font_to_xml()# 2. 生成映射字典
font_map = ufr.crack()# 3. 打印映射结果
print(font_map)

需要先安装以下依赖,然后通过python直接运行。

pip install fonttools pillow ddddocr

效果也是非常不错,但我在查看过程中,发现有些字母大小写识别总是小写,所以手动更改一下映射


最终还是遇到了一个问题,是解密后解码的文字莫名其妙有一个字符乱码,我定位到问题是在解密后的数据就带上了乱码…最终是因为,RSA解密使用的字符串拼接方式,导致了乱码,所以改成直接字节方式就可以了

public static byte[] decryptLongBinary(String encryptedData, PrivateKey privateKey) throws Exception {byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);int keySize = 128; // 1024bit RSA, 128 bytes per blockint chunkSize = keySize; // Each decryption chunk is 128 bytesint inputLength = encryptedBytes.length;ByteArrayOutputStream baos = new ByteArrayOutputStream();// Split the data and decrypt chunk by chunkfor (int i = 0; i < inputLength; i += chunkSize) {int len = Math.min(inputLength - i, chunkSize);byte[] decryptedChunk = cipher.doFinal(encryptedBytes, i, len);baos.write(decryptedChunk);}return baos.toByteArray();
}

就这样,目标完成。




END

关键字:合肥卫来_静态网站开发步骤_可以推广赚钱的软件_seo网站优化培训怎么样

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: