当前位置: 首页 > news >正文

32-字体反爬

本文需要借助工具:fontcreator,或者在线网站:字体设计在线网站

字体反爬介绍

字体反爬是网站常用的前端反爬手段,核心逻辑是用自定义字体文件替代明文文本,爬虫自动化也无法拿到正确的明文数据

字体反爬原理

本文主要讲解的是css层面的字体反爬,css中定义自定义字体的规则叫做@font-face 规则,通过@font-face这个标签会读取字体文件,字体文件中会有对应的映射关系,然后通过映射关系将密文字体转化为明文

字体反爬解决方法以及步骤

解决方法:

1.找字体映射关系

  • 找到字体文件发现字体文件中映射关系少且不变,可以自己手写映射关系
  • 当网页字体映射关系会变时,需要找规律,找出文字映射关系变化逻辑(很难,需要对字体有很深的研究)现在也可以拿下来十个八个文件丢给ai让ai找规律

2.通过坐标描画文字然后用识别库识别来写出映射关系(orc识别)

3.通过on(极少用)

解决步骤:

我们这里主要讲第二种解决方法的步骤,案例地址:shixi僧:

字体文件

第一步,通过请求拿到字体文件并转换

通过请求拿下来字体文件,然后保存到本地:

转换成xml(xml是结构化数据,可以直接用.key(拿到标签),也可以用xpath语法):

源码文件(需注意两个标签):

cmap主要是到时候对应网站上的’乱码’和我们字典中的key,替换’乱码’为正常的字:

glyf中的contour主要是坐标与直曲线,到时按此画图然后识别出文字:

第二步,封装画图加识别的py文件

首先读取文件:

# 解析xml所需库 from lxml import etree # 读取xml文件(xml文件里会有声明:<?xml version="1.0" encoding="UTF-8"?>需要解码:f.read().encode('utf-8')) with open('字体文件.xml', 'r', encoding='utf-8') as f: xml_code = f.read().encode('utf-8') # 解析xml文件(fromstring直接处理xml文件,转换为字符串) font_parser = etree.fromstring(xml_code)

然后xpath解析,提取以及整理名字和坐标:

# xpath语法提取坐标列表 TTGlyph_list = font_parser.xpath('//glyf/TTGlyph') # print(TTGlyph_list) x_y_list = [] for TTGlyph in TTGlyph_list[1:-1]: # print(TTGlyph) if TTGlyph.xpath('./contour[1]'): # print('contour中有数据') font_name = TTGlyph.xpath('./@name') # 拿到名字,即网页字体乱码的映射 contour_list = TTGlyph.xpath('./contour[1]') # 这里是内存地址 # 循环提取contour,然后用xpath提取x y坐标值 for contour in contour_list: x_y = [(x, y) for x, y in zip(contour.xpath('./pt/@x'), contour.xpath('./pt/@y'))] # 这里zip是将x y循环得出的每一个对应位置的元素绑在一起 # 画图需要首尾相连,此处将第一个坐标写入列表尾部 x_y.append(x_y[0]) # print(x_y) # 将所有文字装进一个列表 x_y_list.append(x_y) # print(x_y_list)

然后画图并保存:

# 画图 plt.figure(figsize=(10, 10)) # 创建一个画布,figsize=(10, 10)表示画布的宽和高都是 10 英寸 # 遍历每个图案 for shape in x_y_list: x, y = zip(*[(int(point[0]), (int(point[1]))) for point in shape]) # *是解包运算符,将元组解包再用zip重新分配 # print(x, y) # 绘制多边形 plt.plot(x, y, marker='o') # 连接点的多边形 plt.fill(x, y, alpha=0.3) # 填充多边形 # 隐藏刻度标签 plt.xticks([]) plt.yticks([]) # 设置绘图属性 plt.axis('equal') # 坐标轴比例一致 plt.grid(True) # 保存图片 plt.savefig('图片/' + f'{font_name}.png')

通过ddddocr库识别图片

ocr = ddddocr.DdddOcr() with open('图片/' + f'{font_name}.png', 'rb') as f: image = f.read() res = ocr.classification(image) print(res)

封装此文件成类,方便主py文件调用:

# 解析xml所需库 from lxml import etree import matplotlib # 画图库 matplotlib.use('TkAgg') import matplotlib.pyplot as plt # 识别图片的库 import ddddocr class PaintIdentify: def __init__(self, file_path): self.file_path = file_path # 传递xml文件地址 def parse_file(self, TTGlyph): if TTGlyph.xpath('./contour[1]'): x_y_list = [] # print('contour中有数据') font_name = TTGlyph.xpath('./@name') # 拿到名字,即网页字体乱码的映射 contour_list = TTGlyph.xpath('./contour') # 这里是内存地址 # 循环提取contour,然后用xpath提取x y坐标值 for contour in contour_list: x_y = [(x, y) for x, y in zip(contour.xpath('./pt/@x'), contour.xpath('./pt/@y'))] # 这里zip是将x y循环得出的每一个对应位置的元素绑在一起 # 画图需要首尾相连,此处将第一个坐标写入列表尾部 x_y.append(x_y[0]) # print(x_y) # 将所有文字装进一个列表 x_y_list.append(x_y) self.paint(x_y_list, font_name) res = self.identify(font_name) return (font_name[0], res) return None def paint(self, x_y_list, font_name): # 画图 plt.figure(figsize=(10, 10)) # 创建一个画布,figsize=(10, 10)表示画布的宽和高都是 10 英寸 # 遍历每个图案 for shape in x_y_list: x, y = zip(*[(int(point[0]), (int(point[1]))) for point in shape]) # *是解包运算符,将元组解包再用zip重新分配 # print(x, y) # 绘制多边形 plt.plot(x, y, marker='o') # 连接点的多边形 plt.fill(x, y, alpha=0.3) # 填充多边形 # 隐藏刻度标签 plt.xticks([]) plt.yticks([]) # 设置绘图属性 plt.axis('equal') # 坐标轴比例一致 plt.grid(True) # 保存图片 plt.savefig('图片/' + f'{font_name}.png') def identify(self, font_name): ocr = ddddocr.DdddOcr() with open('图片/' + f'{font_name}.png', 'rb') as f: image = f.read() res = ocr.classification(image) return res def main(self): name_character_dic = {} # 读取xml文件(xml文件里会有声明:<?xml version="1.0" encoding="UTF-8"?>需要解码:f.read().encode('utf-8')) with open(self.file_path, 'r', encoding='utf-8') as f: xml_code = f.read().encode('utf-8') # 解析xml文件(fromstring直接处理xml文件,转换为字符串) font_parser = etree.fromstring(xml_code) # xpath语法提取坐标列表 TTGlyph_list = font_parser.xpath('//glyf/TTGlyph') for TTGlyph in TTGlyph_list[1:-1]: key, value = self.parse_file(TTGlyph) name_character_dic[key] = value return name_character_dic if __name__ == '__main__': paint_identify = PaintIdentify('字体文件.xml') paint_identify.main()

第三步,导入封装库

导入模块,按自己的py文件运行入口的写法写就行:

第四步,根据网页需要的数据进行匹配

经过观察所需的数据来对我们字体映射名来进行调整,然后替换到我们所需的数据中

小结

本文就到此结束,关键步骤已经列出,如有问题及时提出,一起讨论,加油加油

http://www.jsqmd.com/news/605023/

相关文章:

  • 避坑!这些毕设太好抄了,3000+毕设案例推荐第1033期
  • OpenClaw多模态研究助手:千问3.5-35B-A3B-FP8实现论文图表解析与笔记生成
  • OpenClaw飞书机器人集成:Kimi-VL-A3B-Thinking多模态问答助手
  • MGC3130电场式三维手势控制器原理与工程实践
  • 多模态扩展:OpenClaw对接Qwen3-14B镜像实现图文混合处理
  • 平板间二维稳态对流传热方程的软物理信息神经网络实现研究(Python代码实现)
  • OpenClaw学习路径:Qwen3.5-9B从入门到精通
  • OpenClaw+千问3.5-9B会议纪要:语音转文字自动生成重点
  • 小程序如何帮助企业降低获客成本(核心结论)
  • 什么是功率因数 PF?(计算,仿真,验证)
  • Neovim文本编辑器
  • 奇奇怪怪的网站
  • 5个步骤掌握APK-Installer:高效实现Windows安卓应用安装
  • 如何比较不同注册商的域名注册价格_如何查看域名的SEO数据和排名信息
  • 西安保姆服务哪家靠谱
  • Arduino轻量LED节奏控制库:基于位图的同步指示器设计
  • 2026年防雷竣工品牌选型指南:从合规到落地的全维度解析 - 优质品牌商家
  • 光耦电路设计核心:CTR 传输比详解 + 工程实践全要点
  • OpenClaw一键部署教程分享
  • 2025届学术党必备的六大降重复率助手推荐
  • OpenEuler22.03手动编译安装PHP8.3全流程解析
  • 数智赋能订货全链路,千匠网络争做B2B订货平台开发标杆服务商
  • Qt——计算器示例(用户界面与业务逻辑的分离)
  • 2026年上海公司日常保洁TOP5:技术维度拆解与选型参考 - 优质品牌商家
  • 群发总是被屏蔽?教你用 API 实现外部群的“千群千面”精准推送
  • 不止是翻译工具:深度体验Immersive Translate如何优化你的Twitter、Reddit外语信息流阅读
  • Mid-360激光雷达与Fast-LIO2实战:从环境搭建到实时建图
  • zq—算法基础:时空复杂度()
  • 多线程——面试中一个常考的内容(7)
  • 航海小知识 | 电子海图是什么?不止是“把图纸搬进电脑”