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

nodejs:express + js-mdict 网页查询英汉词典,能显示图片

向 DeepSeek R1 提问:
我想写一个Web 前端网页,后台用 nodejs + js-mdict , 实现在线查询英语单词,并能显示图片

1. 项目结构

首先,创建一个项目目录,结构如下:

mydict-app/
├── public/
│   ├── index.html
│   ├── styles.css
│   └── script.js
├── server/
│   └── server.js
├── package.json
└── README.md

英汉词典文件(*.mdx , *.mdd)  已经放在 /js/testdict/ 

2. 安装依赖

在项目根目录下运行以下命令,初始化项目并安装所需的依赖:
cd mydict-app
npm init -y
npm install express
added 69 packages in 6s

npm install js-mdict
added 3 packages in 2s

3. 创建前端页面

在 public/index.html 中创建一个简单的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="jquery.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="search" method="GET" target="iframe"><label id="lab1">请输入:</label><input type="text" name="word" id="word" size="30" placeholder="请输入英文单词"><input type="submit" name="eng_han" value="英译汉"><input type="button" name="btn1" id="btn1" value="前缀查询"><input type="button" name="btn2" id="btn2" value="模糊查询"></form><p></p>
<div style="float:left; width:100%;"><div id="result" style="float:left; width:75%; height:500; border:2px;"><iframe name="iframe" id="iframe" width="100%" height="500"> </iframe></div><div id="alist" style="float:right; width:25%; height:500; border:2px;"></div>
</div><script src="script.js"></script>
</body>
</html>

 在 public 中添加一些英汉字典的样式:oalecd8e.css , oalecd8e.js , uk_pron.png, us_pron.png,
copy jquery-3.2.1.min.js pulibc\jquery.js

在 public/script.js 中编写前端逻辑:

  const iframe = $('#iframe')[0]; // 获取 iframe DOM 元素// 页面加载添加:监听iframe网页点击事件$(document).ready(function(){let listener = window.addEventListener('blur', function(){if (document.activeElement === document.getElementById('iframe')){$('iframe').contents().find('a').click(function(event){event.preventDefault();let a = $(this);if (a){let addr = a.attr('href');if (addr.indexOf('entry://')==0 && addr.indexOf('entry://#')!=0){               let word = encodeURIComponent(addr.substring(8));$.ajax({url: `/search?word=${word}`,method: 'GET',success: function (html) {// 将 HTML 内容加载到 iframe 中//$('#iframe').attr('srcdoc', html);let iframeDoc = iframe.contentDocument || iframe.contentWindow.document;if (html){// 写入 HTML 内容iframeDoc.open();iframeDoc.write(html);iframeDoc.close();}},error: function (error) {console.error('entry:请求失败:', error);}});} else if (addr.indexOf('sound://')==0){let url = "/data/" + addr.substring(8);let mp3 = new Audio(url);mp3.addEventListener("canplaythrough", (event)=> {mp3.play();});mp3.addEventListener('error', (e) => {console.error('play error:', e);});} else {console.log('href='+addr);}}});}});});// 前缀查询
$(function(){$("#btn1").click(function(){$.getJSON("/prefix?word="+$("#word").val(), function(data){let items = [];$.each(data, function(i, item){if (i<=20){items[i] = '<a href="/search?word=' +item+ '" target="iframe">' +item+ "</a><br>";}});let a = items.join('\n');if (a) $('#alist').html(a);})})
});// 模糊查询
$(function(){$("#btn2").click(function(){$.getJSON("/fuzzy?word="+$("#word").val(), function(data){let items = [];$.each(data, function(i, item){if (i<=20){items[i] = '<a href="/search?word=' +item+ '" target="iframe">' +item+ "</a><br>";}});let a = items.join('\n');if (a) $('#alist').html(a);})})
});

4. 创建后端服务器

在 server/server2.js 中编写Node.js服务器代码,使用 express 和 js-mdict 来处理查询请求:

const express = require('express');
const fs = require('fs');
const path = require('path');
const Mdict = require('js-mdict');
//console.log(Mdict);
const app = express();
const port = 8002;// 加载MDict词典文件
//const mdict = new Mdict('path/to/your/dictionary.mdx');
const mdx = new Mdict.MDX('/js/testdict/your英汉词典插图版.mdx');
const mdd = new Mdict.MDD('/js/testdict/your英汉词典插图版.mdd');
//console.log(mdd.locate('\\goods'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// 提供静态文件
app.use(express.static(path.join(__dirname, '../public')));const isWord = (txt) => {// 只允许字母、/、空格、-return /^[a-zA-Z \/\-]+$/.test(txt);
};// 处理查询请求
app.get('/search', (req, res) => {let word = req.query.word;if (word) {let data = mdx.lookup(word);console.log("cha: "+ word);if(data.definition){res.send(data.definition);} else {res.status(200).send('this word not found.');}} else {res.status(400).send('error: No word input');}
});// 处理前缀查询请求
app.get('/prefix', (req, res) => {let word = req.query.word;// 检查word是否合法if (word.length>50 || !isWord(word)) {return res.status(400).send('Invalid input.');}if (word) {let alist = mdx.prefix(word);console.log("pre: "+ word);if(alist.length >0){let wordls = [];alist.forEach(function(value){wordls.push(value.keyText);});  res.json(wordls);} else {res.status(400).send('this word not found');}} else {res.status(400).send('error: No word input');}
});// 处理模糊查询请求
app.get('/fuzzy', (req, res) => {let word = req.query.word;// 检查word是否合法if (word.length>50 || !isWord(word)) {return res.status(400).send('Invalid input.');}if (word) {let alist = mdx.fuzzy_search(word,3,1);console.log("fuzzy: "+ word);if(alist.length >0){let wordls = [];alist.forEach(function(value){wordls.push(value.keyText);});  res.json(wordls);} else {res.status(400).send('this word not found');}} else {res.status(400).send('error: No word input');}
});// 指定目录
const dir1 = "/";// 实现image文件下载,不带路径
app.get('/:fileName', (req, res, next) => {let path1 = '/'; let fileName = req.params.fileName; // 捕获文件名// 检查路径中是否包含非法字符(如 ..)if (fileName.includes('..')) {return res.status(400).send('Invalid path: Path traversal is not allowed.');}//console.log(fileName);let extname = path.extname(fileName);let ext = extname.substring(1).toLowerCase();if (['bmp','gif','jpg','png'].includes(ext)){let filePath = path.join(path1, fileName);//console.log(filePath);let data = mdd.locate(filePath);if (data){console.log('key: '+ data.keyText);//console.log(Buffer.isBuffer(data.definition));if (data.definition){let binaryData = Buffer.from(data.definition, 'base64');//res.setHeader('Content-Type', 'application/octet-stream');res.set({'Content-Type': 'image','Content-Disposition': 'attachment;','Content-Length': Buffer.byteLength(binaryData)});//console.log('bytes: '+ Buffer.byteLength(binaryData));res.end(binaryData);} else {res.status(400).send('error: data.definition is null');}} else {res.status(400).send('error: data is null');}} else {res.status(400).send('filename.ext is not image');}
});// 实现image文件下载,*/是路径
app.get('/*/:fileName', (req, res, next) => {let path1 = req.params[0]; // 捕获 * 匹配的部分let fileName = req.params.fileName; // 捕获文件名// 检查路径中是否包含非法字符(如 ..)if (fileName.includes('..')) {return res.status(400).send('Invalid path: Path traversal is not allowed.');}//console.log(fileName);let extname = path.extname(fileName);let ext = extname.substring(1).toLowerCase();if (['bmp','gif','jpg','png'].includes(ext)){let filePath = path.join(dir1,path1, fileName);//console.log(filePath);let data = mdd.locate(filePath);if (data){console.log('key: '+ data.keyText);//console.log(Buffer.isBuffer(data.definition));if (data.definition){let binaryData = Buffer.from(data.definition, 'base64');//res.setHeader('Content-Type', 'application/octet-stream');res.set({'Content-Type': 'image','Content-Disposition': 'attachment;','Content-Length': Buffer.byteLength(binaryData)});//console.log('bytes: '+ Buffer.byteLength(binaryData));res.end(binaryData);} else {res.status(400).send('error: data.definition is null');}} else {res.status(400).send('error: data is null');}} else {res.status(400).send('filename.ext is not image');}
});app.listen(port, () => {console.log(`Server is running on http://localhost:${port}`);
});

5. 运行项目

在项目根目录下运行以下命令启动服务器:cd /js/mydict-app ;
node server/server2.js

然后打开浏览器,访问 http://localhost:8002,你应该可以看到一个简单的词典查询页面。输入单词并点击查询按钮,页面会显示该单词的释义,并显示插图。

6. 部署

你可以将这个应用部署到任何支持 Node.js 的服务器上。

7. 进一步优化

  • 错误处理: 在前端和后端添加更多的错误处理逻辑。

  • UI 改进: 使用前端框架(如React、Vue.js)来改进用户界面。

  • 缓存: 在后端添加缓存机制,提高查询速度。

  • 多词典支持: 支持加载多个词典文件,并提供切换词典的功能。

希望这些步骤能帮助你实现一个简单的在线英语单词查询应用!

相关文章:

nodejs:express + js-mdict 网页查询英汉词典,能显示图片

向 DeepSeek R1 提问&#xff1a; 我想写一个Web 前端网页&#xff0c;后台用 nodejs js-mdict , 实现在线查询英语单词&#xff0c;并能显示图片 1. 项目结构 首先&#xff0c;创建一个项目目录&#xff0c;结构如下&#xff1a; mydict-app/ ├── public/ │ ├── …...

matlab汽车动力学半车垂向振动模型

1、内容简介 matlab141-半车垂向振动模型 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...

2025.2.16

Web [GDOUCTF 2023]泄露的伪装&#xff1a; 点进去看就是装神弄鬼&#xff0c;那就直接扫描 果然有东西 第一个是php代码 第二个是个文件 访问发现是一样的 分析一下&#xff1a;使用 file_get_contents($cxk) 函数读取 $cxk 变量中指定的 URL 或文件的内容。 如果读取的内…...

图像生成GAN和风格迁移

文章目录 摘要abstract1.生成对抗网络 GAN1.1 算法步骤 2.风格迁移2.1 损失函数2.2 论文阅读2.2.1 简介2.2.2 方法2.2.3 实验2.2.4 结论 3.总结 摘要 本周学习了生成对抗网络&#xff08;GAN&#xff09;与风格迁移技术在图像生成中的应用。首先介绍了GAN模型中生成器与判别器…...

【06】泛型

文章目录 泛型函数中的泛型结构体中的泛型结构体中的方法 枚举中的泛型 泛型 RUST通过在编译时对泛型代码的单态化&#xff08;monomorphization&#xff09;来保证运行效率。即&#xff0c;在编译时对泛型填充具体数据类型转换为特定代码进行编译。 由于RUST编译试图穷举所有…...

1-13 tortoiseGit忽略文件与文件夹

前言&#xff1a; 基于本人对小乌龟操作的学习和思考&#xff0c;仅供参考 1-1 忽略问价和文件夹 有时候我们的一些文件是不想要提交&#xff0c;那么我们可以使用stash的方式给这个文件添加忽略&#xff0c;那么我们现在来给这个实际操作创建一个操作的环境。 右键选中添加到忽…...

ASR强力模型「Whisper」:解密Whisper:AI驱动的语音识别新时代 -

解密Whisper&#xff1a;AI驱动的语音识别新时代 原创 AI小信 别慌G个PT 2024年10月18日 17:54 北京 ❝ 前两天分享了两个TTS模型&#xff0c;今天分享个ASR强力模型「Whisper」。Whisper是OpenAI开发的一个「ASR」(AutomatedSpeechRecognition,自动语音识别)开源模型&#xf…...

【机器学习】向量化使得简单线性回归性能提升

向量化使得简单线性回归性能提升 一、摘要二、向量化运算概述三、向量化运算在简单线性回归中的应用四、性能测试与结果分析 一、摘要 本文主要讲述了向量化运算在简单线性回归算法中的应用。通过回顾传统for循环方式实现的简单线性回归算法&#xff0c;介绍了如何通过最小二乘…...

【kafka系列】消费者

目录 获取消息 1. 消费者获取消息的流程逻辑分析 阶段一&#xff1a;消费者初始化 阶段二&#xff1a;分区分配与重平衡&#xff08;Rebalance&#xff09; 阶段三&#xff1a;消息拉取与处理 阶段四&#xff1a;偏移量提交 核心设计思想 2. 流程 关键点总结 常见参数…...

HackerRank C++面试,中等难度题目 - Attribute Parser

去除字符串首尾的空白字符&#xff08;包括空格、制表符、换行符和回车符&#xff09; void trim(string &s) {size_t start s.find_first_not_of(" \t\n\r");size_t end s.find_last_not_of(" \t\n\r");if (start string::npos) {s ""…...

【ARM】解决ArmDS Fast Models 中部分内核无法上电的问题

1、 文档目标 解决ArmDS Fast Models 中部分内核无法上电的问题。 2、 问题场景 在调用ArmDS的Fast Models中的Cortex-A55的模型&#xff0c;只有Core 0是上电状态&#xff0c;而Core 1处于掉电状态&#xff0c;如图2-1所示&#xff1a; 图2-1 3、软硬件环境 1&#xff09;…...

节目选择器安卓软件编写(针对老年人)

文章目录 需求来源软件界面演示效果源码获取 对爬虫、逆向感兴趣的同学可以查看文章&#xff0c;一对一小班教学&#xff1a;https://blog.csdn.net/weixin_35770067/article/details/142514698 需求来源 由于现在的视频软件过于复杂&#xff0c;某客户想开发一个针对老年人、…...

蓝桥杯之图

图&#xff1a; 对于图来说&#xff0c;重点在于之后的最短路径算法&#xff0c;这边简单做一下了解即可 代码&#xff1a; #include<iostream> #include<string> #include<vector> #include<list> #include<queue> using namespace std; clas…...

中兴光猫修改SN,MAC,修改地区,异地注册,改桥接,路由拨号

前言 请先阅读上一篇博客获取到光猫超级密码电信光猫获取超级密码 电信光猫天翼网关4.0获取超级密码教程 四川电信光猫 中兴 F1855V2 ZXHN F1855V2 telent权限 实战 实测_天翼4.0光猫超级密码-CSDN博客 修改SN-修改地区&#xff0c;光猫异地注册&#xff0c;设置桥接模式&#…...

【kafka系列】Kafka如何保证消息不丢失?

目录 1. 生产者端&#xff1a;确保消息成功发送到Broker 核心机制&#xff1a; 关键步骤&#xff1a; 2. Broker端&#xff1a;持久化与副本同步 核心机制&#xff1a; 关键源码逻辑&#xff1a; 3. 消费者端&#xff1a;可靠消费与Offset提交 核心机制&#xff1a; 关…...

AtCoder Beginner Contest 393 —— E - GCD of Subset 补题 + 题解 python

AtCoder Beginner Contest 393 E - GCD of Subset Problem Statement You are given a sequence A ( A 1 , A 2 , … , A N ) A (A_1, A_2, \dots, A_N) A(A1​,A2​,…,AN​) of length N N N and a positive integer K K K (at most N N N). For each i 1 , 2 , … …...

vue3响应式丢失解决办法(三)

vue3的响应式的理解&#xff0c;与普通对象的区别&#xff08;一&#xff09; vue3 分析总结响应式丢失问题原因&#xff08;二&#xff09; 经过前面2篇文章&#xff0c;知道了响应式为什么丢失了&#xff0c;但是还是碰到了丢失情况&#xff0c;并且通过之前的内容还不能解…...

BY组态:构建灵活、可扩展的自动化系统

引言 在现代工业自动化领域&#xff0c;BY组态&#xff08;Build Your Own Configuration&#xff09;作为一种灵活、可扩展的解决方案&#xff0c;正逐渐成为工程师和系统集成商的首选。BY组态允许用户根据具体需求自定义系统配置&#xff0c;从而优化生产效率、降低成本并提…...

2025 (ISC)²CCSP 回忆录

2025.1.20 广州&#xff0c;周一&#xff0c;我一次性通过了CCSP的考试。 为什么要考证&#xff1f; 个人成长所需 职业热情&#xff1a;做一行爱一行&#xff0c;既然我投入了美好的青春年华到网络安全行业当中&#xff0c;那么对于这个行业最有权威的认证&#xff0c;是肯定…...

强化学习笔记7——DDPG到TD3

前提&#xff1a;基于TD 的方法多少都会有高估问题&#xff0c;即Q值偏大。原因两个&#xff1a;一、TD目标是真实动作的高估。 二&#xff1a;自举法高估。 DDPG 属于AC方法&#xff1a;异策略&#xff0c;适合连续动作空间&#xff0c;因为他的策略网络直接输出的动作&#…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

AWS vs 阿里云:功能、服务与性能对比指南

在云计算领域&#xff0c;Amazon Web Services (AWS) 和阿里云 (Alibaba Cloud) 是全球领先的提供商&#xff0c;各自在功能范围、服务生态系统、性能表现和适用场景上具有独特优势。基于提供的引用[1]-[5]&#xff0c;我将从功能、服务和性能三个方面进行结构化对比分析&#…...

无需布线的革命:电力载波技术赋能楼宇自控系统-亚川科技

无需布线的革命&#xff1a;电力载波技术赋能楼宇自控系统 在楼宇自动化领域&#xff0c;传统控制系统依赖复杂的专用通信线路&#xff0c;不仅施工成本高昂&#xff0c;后期维护和扩展也极为不便。电力载波技术&#xff08;PLC&#xff09;的突破性应用&#xff0c;彻底改变了…...

Modbus转Ethernet IP深度解析:磨粉设备效率跃升的底层技术密码

在建材矿粉磨系统中&#xff0c;开疆智能Modbus转Ethernet IP网关KJ-EIP-101的应用案例是一个重要的技术革新。这个转换过程涉及到两种主要的通信协议&#xff1a;Modbus和Ethernet IP。Modbus是一种串行通信协议&#xff0c;广泛应用于工业控制系统中。它简单、易于部署和维护…...