python 使用OCR 识别woff字体文件

news/2024/9/24 11:21:34/

做数据获取安**时发现请求返回的数据跟woff字体有关,这里写一个使用OCR识别方法,

1、重要部分的原理是解析woff文件,并将woff字体转为图片,并将字体编码与字体图片相对应,便于之后的数据解密解析。

2、使用的是muggle_ocr,当然可以使用其他的图片识别技术。

3、对解析结果进行转换或优化,整体识别率可达98%左右。

python"># from font_transfer import *
import requests
import jsonimport io
import os
import threading
import base64
import muggle_ocr
from PIL import Image, ImageDraw, ImageFont
from fontTools.ttLib import TTFont
from fontTools.ttLib.woff2 import decompress
import tracebackos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'class FontTransfer:_instance_lock = threading.Lock()def __init__(self, font_size=20):self.font_size = font_size  # 字体文字的尺寸self.image_size = self.font_size + 4self.ocr = muggle_ocr.SDK(model_type=muggle_ocr.ModelType.OCR)# self.ocr = ddddocr.DdddOcr(use_gpu=True)self.res_dict = dict()# self.thread_pool = ThreadPoolExecutor(15)# # 线程安全的单例模式# def __new__(cls, *args, **kwargs):#     if not hasattr(cls, '_instance'):#         with FontTransfer._instance_lock:#             if not hasattr(cls, '_instance'):#                 FontTransfer._instance = super().__new__(cls)##         return FontTransfer._instancedef get_chars_from_font(self, ttf):"""从字体文件中获取字体编码、字体字型等信息:param font_path: 字体文件路径 str:return: dict"""# ttf = TTFont(font_path)return {k: v for k, v in ttf['cmap'].getBestCmap().items() if ttf['glyf'][v].xMax}def draw_font_word(self, char_unicode, font, v):"""在画板上画出字体文件中的字型:param char_unicode: unicode编码字符串 str:param board: 画板对象:param font: 字型对象:return: None"""board = Image.new('RGB', (self.image_size, self.image_size), (255, 255, 255))draw = ImageDraw.ImageDraw(board)# 自适应字体在图片中保持居中center_background = (self.image_size / 2, self.image_size / 2)size = draw.textsize(char_unicode, font=font)origin = [center_background[0] - size[0] / 2, center_background[1] - size[1] / 2 - 8]draw.text(tuple(origin), char_unicode, font=font, fill=0)# board.save(f"./{v}.jpg")img_byte = io.BytesIO()board.save(img_byte, format='JPEG')img_data = img_byte.getvalue()result = self.ocr.predict(img_data)# result = self.ocr.classification(img_data)# self.res_dict[v] = resultreturn resultdef get_font_transfer_dict(self, font_path="", font_body=""):"""自适应画出图片的大小,生成字体字型的坐标:param font_path::param font_body: 字体文件的base64 字符串:return:"""if font_path != '':ttf = TTFont(font_path)char_dict = self.get_chars_from_font(ttf)font = ImageFont.truetype(font_path, self.font_size)elif font_body != '':tmp_byts = io.BytesIO()font_bytes = io.BytesIO(base64.b64decode(font_body))ttf = TTFont(font_bytes)char_dict = self.get_chars_from_font(ttf)decompress(font_bytes, tmp_byts)file_bytes = io.BytesIO(tmp_byts.getbuffer())font = ImageFont.truetype(font=file_bytes, size=self.font_size)# thread_arr = []res_dict = dict()for k, v in char_dict.items():char_unicode = chr(k)res = self.draw_font_word(char_unicode, font, v)# thread = self.thread_pool.submit(self.draw_font_word, char_unicode, font, v)# thread_arr.append(thread)res_dict[v] = res# for t in as_completed(res):#     pass# return self.res_dictreturn res_dictdef change_font_encode(self, font_body, font_encode):try:char_dict = self.get_font_transfer_dict(font_body=font_body)font_dict = {}font_change = {'玫': '玖', '参': '叁', '染': '柒', '忏': '仟', '挪': '捌', '青': '壹'}for key, value in char_dict.items():if value in font_change.keys():font_dict[key] = font_change[value]else:font_dict[key] = valuefor key, value in font_dict.items():font_encode = font_encode.replace(key, value)return font_encodeexcept Exception as e:traceback.print_exc()return font_encodefft = FontTransfer(font_size=50)def change_font(font_body, text):text = '%r' % texttext = text.replace('\\U000', 'uni').replace("'", '').replace('\\', '')res = fft.change_font_encode(font_body=font_body, font_encode=text)return rescookie = ''
headers = {'accept': '*/*','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36','cookie': cookie
}json_data = {'type': 'HOUSE','pageNum': 1,'pageSize': 50,'condition': {'communityId': xxxxx,'buildingOpenId': 'xxxxxx','unitOpenId': '','floorOpenId': 'xxxxx','bizType': 'HOUSE','keyword': '',},
}response = requests.post('https://x.xxxx.com/landlord/cross/v1/communities/buildings', headers=headers, json=json_data)
json_data = json.loads(response.text)if json_data['status'] == "0":data = json_data['data']fontInfo = data['fontInfo']woffFontBody = fontInfo['woffFontBody']results = data['results']item_count = len(results)for res in results:encryptBizName = res['encryptBizName']decryptBizName = change_font(woffFontBody, text=encryptBizName)print(encryptBizName, decryptBizName)
else:print(json_data)

该部分代码仅用于学习使用。


http://www.ppmy.cn/news/1463680.html

相关文章

【MySQL精通之路】SQL优化(1)-查询优化(1)-WHERE子句

主博客: 【MySQL精通之路】SQL优化(1)-查询优化-CSDN博客 下一篇: 【MySQL精通之路】SQL优化(1)-查询优化(2)-范围查询优化-CSDN博客 本节讨论可用于处理WHERE子句的优化。 这些示例使用SELECT语句,但DELETE和UPDATE语句中的WHERE子句也适…

【吊打面试官系列】Java高并发篇 - Java 死锁以及如何避免?

大家好,我是锋哥。今天分享关于 【Java 死锁以及如何避免?】面试题,希望对大家有帮助; Java 死锁以及如何避免? Java 中的死锁是一种编程情况,其中两个或多个线程被永久阻塞,Java 死锁情况出现至…

Python Requests库中data与json参数的区别

这里写目录标题 概述详细分析综合应用结论 概述 在Python的Requests库中,data和json参数常用于在HTTP请求中发送数据。它们的主要区别在于数据的编码方式和Content-Type头部。data参数通常用于发送表单数据,其数据会被编码为application/x-www-form-url…

基于Kubeeasy安装Kubernetes-v1.22.1版本(安装报错已解决)

基础环境准备 将提供的安装包 chinaskills_cloud_paas_v2.0.2.iso 上传至 master 节点 /root 目录,并解压 到 /opt 目录: [rootlocalhost ~]# ll total 7446736 -rw-------. 1 root root 1579 Mar 7 22:46 anaconda-ks.cfg -rw-r--r--. 1 root …

自定义原生小程序顶部及获取胶囊信息

需求:我需要将某个文字或者按钮放置在小程序顶部位置 思路:根据获取到的顶部信息来定义我需要放的这个元素样式 * 这里我是定义某个指定页面 json:给指定页面的json中添加自定义设置 "navigationStyle": "custom" JS&am…

基于Kafka的日志采集

目录 前言 架构图 资源列表 基础环境 关闭防护墙 关闭内核安全机制 修改主机名 添加hosts映射 一、部署elasticsearch 修改limit限制 部署elasticsearch 修改配置文件 启动 二、部署filebeat 部署filebeat 添加配置文件 启动 三、部署kibana 部署kibana 修…

操作系统实验--终极逃课方法

找到图片里的这个路径下的文件 ,结合当前题目名称,把文件内容全部删除,改为print print的内容为下图左下角的预期输出的内容

一个普通双非女生的秋招之路

大家好,我是小布丁。 先简单地做个自我介绍: 我今年本科毕业于某双非院校(属于那种没什么人听说过的小学校),学的是计算机专业,英语四级水平(没办法,六级确实没过)。我本…