文档智能翻译,保留文档原有布局,版式还原

翻译能力:

  1. 使用讯飞的AI翻译能力:机器翻译 niutrans - 语音扩展 - 讯飞开放平台
  2. API: 机器翻译niutrans API 文档 | 讯飞开放平台文档中心
执行效果:

    原文档:

   翻译还原的文档:

源码如下:

import datetime
import hashlib
import base64
import hmac
import json
import requests
import threading
from threading import Thread
from queue import Queue, Full, Empty
from docx import Document
from concurrent.futures import ThreadPoolExecutor

# 全局配置
APPId = "xxx"
APISecret = "xxxx"
APIKey = "xxxx"
HOST = "ntrans.xfyun.cn"


# 线程池
class ThreadPool:
    def __init__(self, size: int, max_workers: int):
        self.max_workers = max_workers  # 最大可运行线程数
        self._has_th = []  # 已启动线程数
        self._pending = Queue(maxsize=max_workers)  # 阻塞线程数
        self._task = Queue(maxsize=size)  # 任务等待队列
        self._close = False  # 线程池是否关闭

    def worker(self, *args):
        """
        任务的执行者
        :param args: 运行任务与任务参数
        :return:
        """
        th = threading.current_thread()
        self._has_th.append(th)
        # 执行创建线程时分配的任务
        func, *args = args
        func(*args)
        # 线程阻塞,进入等待任务队列
        while True:
            self._pending.put(1)
            try:
                # 获取任务
                task, *arg = self._task.get(timeout=1)
            except Empty:
                self._pending.get()
                return
            # 从等待队列取出并执行任务
            self._pending.get()
            task(arg)

    def submit(self, func, args):
        # 线程池关闭
        if self._close:
            raise RuntimeError("thread closed")
        # 当无空闲线程且当前线程数小于最大可运行线程数,创建新的线程。
        elif self._pending.empty() and len(self._has_th) < self.max_workers:
            th = Thread(target=self.worker, args=(func, args))
            # th.setDaemon(True) # 主进程结束是否结束子进程 默认False
            th.start()
        else:
            try:
                # 当所有线程都在运行,且线程数达到最大值,任务进入等待队列
                self._task.put((func, args), block=True, timeout=25)
            except Full:
                # 等待进入队列超时
                raise TimeoutError("任务提交超时")

    def close(self):
        self._close = True


# 鉴权
class get_result(object):
    def __init__(self, host):
        # 应用ID(到控制台获取)
        self.APPID = APPId
        # 接口APISercet(到控制台机器翻译服务页面获取)
        self.Secret = APISecret
        # 接口APIKey(到控制台机器翻译服务页面获取)
        self.APIKey = APIKey

        # 以下为POST请求
        self.Host = host
        self.RequestUri = "/v2/ots"
        # 设置url
        # print(host)
        self.url = "https://" + host + self.RequestUri
        self.HttpMethod = "POST"
        self.Algorithm = "hmac-sha256"
        self.HttpProto = "HTTP/1.1"

        # 设置当前时间
        curTime_utc = datetime.datetime.utcnow()
        self.Date = self.httpdate(curTime_utc)
        # 设置业务参数
        # 语种列表参数值请参照接口文档:https://www.xfyun.cn/doc/nlp/niutrans/API.html
        self.BusinessArgs = {
            "from": "en",
            "to": "cn",
        }

    def hashlib_256(self, res):
        m = hashlib.sha256(bytes(res.encode(encoding='utf-8'))).digest()
        result = "SHA-256=" + base64.b64encode(m).decode(encoding='utf-8')
        return result

    def httpdate(self, dt):
        """
        Return a string representation of a date according to RFC 1123
        (HTTP/1.1).

        The supplied date must be in UTC.

        """
        weekday = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()]
        month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
                 "Oct", "Nov", "Dec"][dt.month - 1]
        return "%s, %02d %s %04d %02d:%02d:%02d GMT" % (weekday, dt.day, month,
                                                        dt.year, dt.hour, dt.minute, dt.second)

    def generateSignature(self, digest):
        signatureStr = "host: " + self.Host + "\n"
        signatureStr += "date: " + self.Date + "\n"
        signatureStr += self.HttpMethod + " " + self.RequestUri \
                        + " " + self.HttpProto + "\n"
        signatureStr += "digest: " + digest
        signature = hmac.new(bytes(self.Secret.encode(encoding='utf-8')),
                             bytes(signatureStr.encode(encoding='utf-8')),
                             digestmod=hashlib.sha256).digest()
        result = base64.b64encode(signature)
        return result.decode(encoding='utf-8')

    def init_header(self, data):
        digest = self.hashlib_256(data)
        # print(digest)
        sign = self.generateSignature(digest)
        authHeader = 'api_key="%s", algorithm="%s", ' \
                     'headers="host date request-line digest", ' \
                     'signature="%s"' \
                     % (self.APIKey, self.Algorithm, sign)
        # print(authHeader)
        headers = {
            "Content-Type": "application/json",
            "Accept": "application/json",
            "Method": "POST",
            "Host": self.Host,
            "Date": self.Date,
            "Digest": digest,
            "Authorization": authHeader
        }
        return headers

    def get_body(self, text):
        content = str(base64.b64encode(text.encode('utf-8')), 'utf-8')
        postdata = {
            "common": {"app_id": self.APPID},
            "business": self.BusinessArgs,
            "data": {
                "text": content,
            }
        }
        body = json.dumps(postdata)
        # print(body)
        return body

    def call_url(self, text):
        if self.APPID == '' or self.APIKey == '' or self.Secret == '':
            print('Appid 或APIKey 或APISecret 为空!请打开demo代码,填写相关信息。')
        else:
            code = 0
            body = self.get_body(text)
            headers = self.init_header(body)
            # print(self.url)
            response = requests.post(self.url, data=body, headers=headers, timeout=8)
            status_code = response.status_code
            # print(response.content)
            if status_code != 200:
                # 鉴权失败
                print("Http请求失败,状态码:" + str(status_code) + ",错误信息:" + response.text)
                print("请根据错误信息检查代码,接口文档:https://www.xfyun.cn/doc/nlp/niutrans/API.html")
                return None
            else:
                # 鉴权成功
                respData = json.loads(response.text)
                # print(respData)
                # 以下仅用于调试
                code = str(respData["code"])
                if code != '0':
                    print("请前往https://www.xfyun.cn/document/error-code?code=" + code + "查询解决办法")
                else:
                    return respData["data"]["result"]["trans_result"]["dst"]

            return None


def ai_translate(text):
    if text.isspace():
        print("the data is null")
        return
    ret = get_result(HOST).call_url(text)
    print(ret)
    return ret


def split_form(parm_form):
    print("split_form: ")
    try:
        for row in parm_form.rows:  # 从表格第一行开始循环读取表格数据
            for cell in row.cells:  # 遍历每一个单元格
                for j in range(len(row.cells)):
                    if ("\n" != row.cells[j].text) & ("\r" != row.cells[j].text) & (0 != len(row.cells[j].text)) & \
                            ("\r\n" != row.cells[j].text) & (not row.cells[j].text.isspace()):
                        row.cells[j].text = ai_translate(row.cells[j].text)
                        print(row.cells[j].text)
    except AttributeError as e:
        print("parm has no rows")


def split_paragraph_runs(parm_paragraph):
    print("split_paragraph_runs: ")
    try:
        runs = parm_paragraph.runs
        for i, run in enumerate(runs):
            if run.text:
                if ("\n" != run.text) & ("\r" != run.text) & (0 != len(run.text)) & ("\r\n" != run.text) & (
                        not run.text.isspace()):
                    run.text = ai_translate(run.text)
    except AttributeError as e:
        print("parm has no text")


if __name__ == '__main__':
    thread_pool = ThreadPoolExecutor(max_workers=6)
    start_time = datetime.datetime.now()
    doc = Document('../source/src1.docx')  # exist.docx为文件名
    # 表格内容翻译
    tables = doc.tables  # 获取文件中的表格集
    print("表格数量:", len(tables))  # 获取文件中的表格数量
    for table in tables:  # 遍历每一个表格
        thread_pool.submit(split_form, table)

    # 文本内容翻译
    for paragraph in doc.paragraphs:
        if ("\n" != paragraph.text) & ("\r" != paragraph.text) & (0 != len(paragraph.text)) & (
                "\r\n" != paragraph.text) & (not paragraph.text.isspace()):
            thread_pool.submit(split_paragraph_runs, paragraph)
    thread_pool.shutdown(wait=True)
    doc.save('../source/dst.docx')

    end_time = datetime.datetime.now()
    print("cost total time:", (end_time - start_time).seconds)
 

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

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

相关文章

用户规模破亿!基于文心一言的创新应用已超4000个

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

基于Java Swing的图书管理系统

一、项目总体架构 本项目基于Java Swing框架&#xff0c;数据库采用的是MySQL。项目文件夹如下&#xff1a; 二、项目截图 1.登录和注册界面 2.用户界面 3.管理员管理图书类别 4.管理员管理书籍 5.管理员管理用户 项目总体包括源代码和课程论文&#xff0c;需要源码的…

【Recruitment Mercedes Benz】

Network I) JDII) IPv4与IPv6之间的区别是什么III) was advices3.1&#xff09; 防火墙&#xff0c;配置&#xff0c;数据的in/out (data flow in or flow out)3.2&#xff09; 域名&#xff0c;网址&#xff0c;端口3.3) 三次握手&#xff0c;四次挥手3.4) TCP/IP, 几层协议&a…

Java生态系统的进化:从JDK 1.0到今天

目录 前言 JDK 1.0&#xff1a;开启Java时代 JDK 1.1&#xff1a;Swing和内部类 JDK 1.2&#xff1a;Collections框架和JIT编译器 JDK 1.5&#xff1a;引入泛型和枚举 JDK 1.8&#xff1a;Lambda表达式和流 JDK 11以后&#xff1a;模块化和新特性 未来展望 总结 作者简…

奇富科技跻身国际AI学术顶级会议ICASSP 2024,AI智能感知能力迈入新纪元

近日&#xff0c;2024年IEEE声学、语音与信号处理国际会议ICASSP 2024&#xff08;2024 IEEE International Conference on Acoustics, Speech, and Signal Processing&#xff09;宣布录用奇富科技关于语音情感计算的最新研究成果论文“MS-SENet: Enhancing Speech Emotion Re…

Python从入门到熟练

文章目录 Python 环境Python 语法与使用基础语法数据类型注释数据类型介绍字符串列表元组集合字典 类型转换标识符运算符算数运算符赋值运算符复合运算符 字符串字符串拼接字符串格式化 判断语句bool 类型语法if 语句if else 语句if elif else 语句 循环语句while循环for 循环r…

Python可视化之Matplotlib

文章目录 Matplotlib与可视化分析简单图形的绘制pylot的高级功能添加图例与注释 Matplotlib与可视化分析 我们之前对数据的处理与分析&#xff0c;其实最终还是要利用可视化工具进行更加直观的输出 我们开业通过 pip install matplotlib命令来安装对应的模块 简单图形的绘制…

WEB渗透—PHP反序列化(九)

Web渗透—PHP反序列化 课程学习分享&#xff08;课程非本人制作&#xff0c;仅提供学习分享&#xff09; 靶场下载地址&#xff1a;GitHub - mcc0624/php_ser_Class: php反序列化靶场课程&#xff0c;基于课程制作的靶场 课程地址&#xff1a;PHP反序列化漏洞学习_哔哩…

k8s集群etcd备份与恢复

一、前言 k8s集群使用etcd集群存储数据&#xff0c;如果etcd集群崩溃了&#xff0c;k8s集群的数据就会全部丢失&#xff0c;所以需要日常进行etcd集群数据的备份&#xff0c;预防etcd集群崩溃后可以使用数据备份进行恢复&#xff0c;也可用于重建k8s集群进行数据恢复 二、备份…

k8s的二进制部署(源码包部署)

实验条件&#xff1a; 主机名 IP地址 组件 作用 master01 20.0.0.17 kube-apiserver、kube-controller-manager、kube-scheduler、etcd k8s部署 master02 20.0.0.27 kube-apiserver、kube-controller-manager、kube-scheduler node01 20.0.0.37 kubelet、kube-pro…

鸿蒙开发之崩溃信息收集FaultLogger

前申&#xff1a;果然系统的API没有让我失望&#xff0c;日志完全看不出来崩溃原因所在 一、使用 logCrash() {FaultLogger.query(FaultLogger.FaultType.JS_CRASH,(err,val) > {if (err) {console.log(fault log get an errJSON.stringify(err))return}let len val.lengt…

完全背包问题,原理剖析,公式推导,OJ详解

文章目录 前言一、完全背包的状态设计1、状态设计2、状态转移方程3、对比0/1背包问题4、时间复杂度分析 二、完全背包问题的优化1、时间复杂度优化2、空间复杂度优化 三、OJ练习裸题完全背包离散化最小值 前言 完全背包问题&#xff0c;相比0/1背包问题&#xff0c;实就每个物品…