python 使用OCR 识别woff字体文件

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

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

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

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

python 复制代码
# from font_transfer import *
import requests
import json

import 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 traceback

os.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 + 4
        self.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._instance

    def 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] = result
        return result

    def 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_dict

        return res_dict

    def 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] = value

            for key, value in font_dict.items():
                font_encode = font_encode.replace(key, value)

            return font_encode
        except Exception as e:
            traceback.print_exc()
            return font_encode

fft = FontTransfer(font_size=50)


def change_font(font_body, text):
    text = '%r' % text
    text = text.replace('\\U000', 'uni').replace("'", '').replace('\\', '')
    res = fft.change_font_encode(font_body=font_body, font_encode=text)
    return res



cookie = ''
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)

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

相关推荐
LIN-JUN-WEI15 分钟前
[ESP32]VSCODE+ESP-IDF环境搭建及blink例程尝试(win10 win11均配置成功)
c语言·开发语言·ide·vscode·单片机·学习·编辑器
望获linux1 小时前
【Linux基础知识系列】第四十三篇 - 基础正则表达式与 grep/sed
linux·运维·服务器·开发语言·前端·操作系统·嵌入式软件
ahead~1 小时前
【大模型入门】访问GPT_API实战案例
人工智能·python·gpt·大语言模型llm
留不住丨晚霞2 小时前
说说SpringBoot常用的注解?
java·开发语言
大模型真好玩2 小时前
准确率飙升!GraphRAG如何利用知识图谱提升RAG答案质量(额外篇)——大规模文本数据下GraphRAG实战
人工智能·python·mcp
19892 小时前
【零基础学AI】第30讲:生成对抗网络(GAN)实战 - 手写数字生成
人工智能·python·深度学习·神经网络·机器学习·生成对抗网络·近邻算法
hardStudy_h2 小时前
C++——内联函数与Lambda表达式
开发语言·jvm·c++
applebomb2 小时前
没合适的组合wheel包,就自行编译flash_attn吧
python·ubuntu·attention·flash
艾莉丝努力练剑2 小时前
【C语言】学习过程教训与经验杂谈:思想准备、知识回顾(三)
c语言·开发语言·数据结构·学习·算法
Chasing__Dreams2 小时前
python--杂识--18.1--pandas数据插入sqlite并进行查询
python·sqlite·pandas