python:bottle + eel 模仿 mdict 查英汉词典

news2025/1/19 22:19:02

Eel 是一个轻量的 Python 库,用于制作简单的类似于离线 HTML/JS GUI 应用程序,并具有对 Python 功能和库的完全访问权限。

Eel 托管一个本地 Web 服务器,允许您使用 Python 注释函数(annotate functions),可以从 JavaScript 调用python函数,也可以从python调用JavaScript函数。

Eel 基于 Bottle 和 gevent 构建,它们提供了类似于 JavaScript 的异步事件循环。

用chrome 访问 https://www.lfd.uci.edu/~gohlke/pythonlibs/#python-lzo
下载 python_lzo-1.14-cp38-cp38-win_amd64.whl
pip install python_lzo-1.14-cp38-cp38-win_amd64.whl

pip install readmdict ;

pip install eel

Eel-0.16.0.tar.gz (24 kB)
bottle-websocket-0.2.9.tar.gz (2.0 kB)
whichcraft-0.6.1-py2.py3-none-any.whl (5.2 kB)
gevent_websocket-0.10.1-py3-none-any.whl (22 kB)
gevent-23.9.1-cp310-cp310-win_amd64.whl (1.5 MB)
zope.event-5.0-py3-none-any.whl (6.8 kB)

编写 mdict_eel.py 如下

# -*- coding: utf-8 -*-
""" web server 用于查询英汉词典 """
import os
import sys
import json
import time
from readmdict import MDX
import bottle
from bottle import route, post, request, static_file
import eel
import win32com.client  # TTS
sapi = win32com.client.Dispatch("SAPI.SpVoice")

start_time = time.time()
os.chdir("/mdict")
# 加载.mdx文件
filename = "your.mdx"
mdx = MDX(filename)
headwords = [*mdx]       # 单词名列表
items = [*mdx.items()]   # 释义html源码列表
n = len(headwords)
m = len(items)
if n == m:
    print(f'{filename} 加载成功:共{n}条')
    end_time = time.time()
    print('cost %f second' % (end_time - start_time))
else:
    print(f'ERROR:加载失败 {n}!={m}')
    sys.exit(1)

app = bottle.Bottle()

# 静态资源的目录通常称为public或static
@app.route('/<filepath:path>')
def server_static(filepath):
    return static_file(filepath, root='./')

def eng_han(txt):
    """ 英译中 """
    if not txt.isascii():
        return 'Maybe text is not english'
    word = txt.encode()
    word1 = txt.capitalize().encode() # 第1个字母变大写
    global headwords, items
    try: # 查词,返回单词和html文件
        if word in headwords:
            wordIndex = headwords.index(word)
        else:
            wordIndex = headwords.index(word1)
        word,html = items[wordIndex]
        result = html.decode()
        if result.startswith('@@@LINK='):
            w = result[8:].strip()
            result = '<a href="/trans?txt='+w+ '">' +w+ '</a>'
        else:
            result = result.replace('<img src="','<img src="/data/')
            result = result.replace('"/thumb/', '"data/thumb/')
            result = result.replace('entry://', '/trans?txt=')
            #result = result.replace('sound://','/data/')
    except:
        result = f"<h3>{txt} is not in word_list.</h3>"
    return result

@app.route('/prefix')
def prefix():
    """ 前缀匹配 """
    try:
        txt = request.query.txt
    except:
        return '1: get txt error'
    if len(txt.strip()) ==0:
        return 'text is null'
    print(txt)
    if len(txt) > 1:
        alist = []
        word = txt.strip().lower() # 字母变小写
        for hw in headwords:
            hws = hw.decode().lower()
            if hws.startswith(word):
                hws = hw.decode()
                alist.append(hws)
        if len(alist) > 0:
            result = json.dumps(alist)
        else:
            result = '["not found"]'
    else:
        result = '["length too short"]'
    return result

@app.route('/trans')
def trans():
    """ method=GET 英译中"""
    try:
        txt = request.query.txt
    except:
        return '1: get txt error'
    if len(txt.strip()) ==0:
        return 'text is null'
    print(txt)
    result = eng_han(txt)
    return result

@app.route('/trans', method='POST')
def trans():
    """ 英译中 """
    try:
        #txt = request.forms.get('txt')
        txt = request.POST.get('txt')
    except:
        return '1: get txt error'
    if len(txt.strip()) ==0:
        return 'text is null'
    print(txt)
    result = eng_han(txt)
    return result

eel.init('.')

@eel.expose           # 暴露python函数给js
def py_speak(txt):
    """ text TTS """
    if txt.strip() !='':
        sapi.Speak(txt)

#eel.start('index.html', app=middleware)
eel.start('index5.html', app=app, size=(1000,600))
#eel.start('index5.html', app=app, mode="edge", size=(1000,600))

编写 index5.html 如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>查询英汉词典</title> 
    <script src="/eel.js"></script>
    <script src="jquery-3.2.1.min.js"></script>
<style>
/* portrait 判断为竖屏 */
@media only screen and (orientation: portrait){
     #lab1 {display:none;}
} 
/* landscape 判断为横屏 */ 
@media only screen and (orientation: landscape){
     #lab1 {display: ;} 
}    
</style>
</head>
<body>
  <form name="form" id="form" action="trans" method="POST" target="iframe">
    <label id="lab1">请输入:</label>
    <input type="text" name="txt" id='txt' size="30" placeholder="请输入 a word">
    <input type="submit" name="eng_han" value="英译汉">
    <input type="button" name="btn1" id="btn1" value="前缀查询">
    <input type="button" name="btn2" id="btn2" value="TTS读音" onclick="tts2();">
  </form>
  <p></p>
<div style="float:left; width:100%;">
  <div id="result" style="float:left; width:80%; height:400; border:2px;">
    <iframe name="iframe" id="iframe" width="100%" height="400"> </iframe>
  </div>
  <div id="alist" style="float:right; width:20%; height:400; border:2px;">
  </div>
</div>
  
  <script type="text/javascript">
    $(function(){
      $("#btn1").click(function(){
        $.getJSON("/prefix?txt="+$("#txt").val(), function(data){
          var items = [];
          $.each(data, function(i, item){
            if (i<=20){
              items[i] = '<a href="/trans?txt=' +item+ '" target="iframe">' +item+ "</a><br>";
            }
          });
          var a = items.join('\n');
          if (a) $('#alist').html(a);
        })
      })
    });

    // TTS
    function tts() {
        var txt = document.getElementById('txt').value;
        if (txt.length >1) eel.py_speak(txt);
    }

    // 屏幕双击取词
    function tts2() {
        // 获取iframe里的选择内容
        var select = window.frames['iframe'].getSelection();
        var txt = select.toString();
        if (txt.length >1) eel.py_speak(txt);
        else tts();       
    }

  // 页面加载添加:监听iframe网页点击事件
  $(document).ready(function(){
    var listener = window.addEventListener('blur', function(){
      if (document.activeElement === document.getElementById('iframe')){
        $('iframe').contents().find('a.fayin').click(function(event){
          event.preventDefault();
          var a = $(this);
         if (a){
          var addr = a.attr('href');
          if (addr.indexOf('sound://')==0){
            var url = "/data" + addr.substring(7);
            var mp3 = new Audio(url);
            mp3.addEventListener("canplaythrough", (event)=> {
               mp3.play();
            });
          } else {
            alert('href='+addr);
          }
         }
        })
      }        
    });
  });
  </script> 
</body>
</html>

运行 python mdict_eel.py 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDLE、Anaconda安装与使用

博主&#xff1a;命运之光 专栏&#xff1a;Python程序设计​​​​​ 目录 Python下载和安装 Anaconda安装和使用 Python程序运行方式 Python下载和安装 常用集成开发环境 IDE 默认编程环境&#xff1a; IDLE---初学者&#xff08; Download Python | Python.org &#x…

自动群发节日祝福,1 行 Python 代码搞定,小白可用

想了解更多精彩内容&#xff0c;快来关注程序员晚枫 大家节日快乐&#xff0c;这里是程序员晚枫&#xff0c;小红薯也叫这个名字。 今天给大家分享一个实用功能&#xff1a;自动群发祝福消息。 我相信社会人都体会过&#xff0c;过年过节给别人群发祝福消息的无奈&#xff0…

前沿研究|16s+宏基因组binning揭示大型藻类附生微生物群落核心组成

发表期刊&#xff1a;Microbiome 发表时间&#xff1a;2023 影响因子&#xff1a;15.5 DOI: 10.1186/s40168-023-01559-1 研究背景 大型藻类附生微生物群落是新型酶类和化合物的丰富资源&#xff0c;在维持沿海系统的高生物生产力和生物多样性方面发挥着重要的作用。但迄今…

华为乾坤区县教育安全云服务解决方案(2)

本文承接&#xff1a; https://blog.csdn.net/qq_37633855/article/details/133276200?spm1001.2014.3001.5501 重点讲解华为乾坤区县教育安全云服务解决方案的部署流程。 华为乾坤区县教育安全云服务解决方案&#xff08;2&#xff09; 课程地址解决方案部署整体流程组网规划…

Prettier - Code formatter格式化规则文件

文章目录 前言安装使用 前言 先前公司在规范代码时,由于个人业务繁忙跟技术总监是后端出身用的IDEA不熟悉vsCode;以及大多数时都自己一个人负责一个项目,当时并不看重这些;最近在整理vue3tsvite的脚手架模板(平时工作用的react),开始整理格式化代码,方便之后 vue 和 react 中应…

(附源码)springboot体检预约APP 计算机毕设16370

目 录 摘要 1 绪论 1.1开发背景 1.2研究现状 1.3springboot框架介绍 1.4论文结构与章节安排 2 Springboot体检预约APP系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1 数据添加流程 2.2.2 数据…

什么是Promise链(Promise chaining)?它在异步编程中的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是 Promise 链&#xff1f;⭐ 异步编程中的作用⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、…

Java后端接口编写流程

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Java后端接口编写流程 Java后端接口编写流程&#xff0c;更具业务逻辑编写Java后端接口&#xff0c;提供给前端访问 实现逻辑流程 POJO&#xff1a;实体类编写 Data B…

架构设计第七讲:数据巡检系统之daily线上表结构自动化比对

架构设计第七讲&#xff1a;数据巡检系统之daily&线上表结构自动化比对 本文是架构设计第七讲&#xff0c;数据巡检系统之daily&线上表结构自动化比对&#xff0c;避免正式环境与测试环境数据库/表、列结构不一致带来问题。 文章目录 架构设计第七讲&#xff1a;数据巡…

36 二叉树中序遍历

二叉树中序遍历 题解1 递归题解2 迭代 给定一个二叉树的根节点 root &#xff0c;返回它的 中序 遍历 。 提示&#xff1a; 树中节点数目在范围 [0, 100] 内-100 < Node.val < 100 进阶: 递归算法很简单&#xff0c;你可以通过迭代算法完成吗&#xff1f; 题解1 递归…

Python绘图系统23:导入多个坐标轴的数据

文章目录 单轴导入多轴导入多文件导入合并导入源代码 Python绘图系统&#xff1a; 前置源码&#xff1a; Python打造动态绘图系统&#x1f4c8;一 三维绘图系统 &#x1f4c8;二 多图绘制系统&#x1f4c8;三 坐 标 轴 定 制&#x1f4c8;四 定制绘图风格 &#x1f4c8;五 数据…

第一章 数据可视化和matplotlib

Python数据可视化 第一章 数据可视化和matplotlib 1.数据可视化概述 1.1.什么是数据可视化 ​ 数据可视化旨在借助图形化的手段&#xff0c;将一组数据以图形的形式表示&#xff0c;并利用数据分析和开发工具发现其中未知信息的处理过程。 ​ 数据可视化发展历史 ​ 可视化…

Spring IOC容器实例化Bean整体流程图

SpringBean实例化的基本流程-CSDN博客 Spring容器中的BeanDefinitionReader读取器&#xff0c;读取xml配置文件&#xff0c;解析每一个bean标签&#xff0c;将bean标签中信息封装到BeanDefinition对象中&#xff0c;该对象的集合存储到BeanDefinitionMap中&#xff0c;然后Spri…

Cocos Creator3.8 实战问题(三)去除scrollview背景色和label 对齐方式设置无效问题

1、 scrollview 默认背景是白色的&#xff0c; 我们不想要 scrollview 默认的背景颜色&#xff0c;怎么办&#xff1f; 设置 scrollview的color为透明吗&#xff1f; 不对&#xff0c;这会导致 view节点完全透明。 解决方法&#xff1a;直接删除scrollview 的Spritre frame就…

船用低速发动机缸压在线监测系统

LabVIEW开发船用低速发动机缸压在线监测系统 船用发动机结构复杂&#xff0c;部件相互连接&#xff0c;运行环境恶劣&#xff0c;使其更容易发生故障。如果船用发动机发生故障或工作状态不佳&#xff0c;将增加造成经济损失和威胁船舶安全的机。为了减少故障的发生&#xff0c…

【Kettle】Kettle部署与运行

一、部署 1.安装java 此处安装openjdk1.8&#xff0c;可用yum、apt、源码等方式安装&#xff0c;具体安装方式略。 2.安装kettle 1.下载 https://www.hitachivantara.com/en-us/products/pentaho-platform/data-integration-analytics/pentaho-community-edition.html 此…

Unity中UI Shader遮罩RectMask2D

文章目录 前言一、需要定义一个变体UNITY_UI_CLIP_RECTUNITY_UI_CLIP_RECT 二、需要申明一个_ClipRect,这是使用上面这个变体需要使用的&#xff0c;这个属性并没有在Properties声明1、现在我们用简单的代码测试一下 _ClipRect 的使用然后我们基于以上的基础&#xff0c;让 内层…

二、局域网联机

目录 1.下载资源包 2.配置NetworkManager 3.编写测试UI 1.下载资源包 2.配置NetworkManager &#xff08;1&#xff09;在Assets/Prefabs下创建Network Prefabs List 相应设置如下&#xff1a; &#xff08;2&#xff09; 创建空物体“NetworkManager”并挂载NetworkMan…

MySQL数据库——索引(5)-索引使用(上),验证索引效率、最左前缀法则、范围查询、索引失效情况、SQL提示

目录 索引使用 验证索引效率 最左前缀法则 范围查询 索引失效情况 索引列运算 字符串不加引号 模糊查询 or连接条件 数据分布影响 SQL提示 use index ignore index force index 索引使用&#xff08;上&#xff09; 验证索引效率 在讲解索引的使用原则之前&…

c语言常用语法,长时间不用容易忘。

关键字 auto 声明自动变量const 定义常量&#xff0c;如果一个变量被 const 修饰&#xff0c;那么它的值就不能再被改变extern 声明变量或函数是在其它文件或本文件的其他位置定义register 声明寄存器变量signed 声明有符号类型变量或函数static 声明静态变量&#xff0c;修饰…