当前位置: 首页 > 后端技术 > Node.js

记得一次翻译站的经历

时间:2023-04-04 00:38:42 Node.js

在做这个记录之前,我刚刚完成了使用无人机作为公司前端项目的持续交付工具的实践。在写教程之前,我把官方文档摘下来,做了一个翻译站。经过一番实践,卡住了不能频繁调用google翻译,项目没法进行。最后觉得过程涉及的内容比较多,所以记录下来分享给大家。本次体验涉及到以下知识:wget抓取网站使用基于python的翻译工具使用nodejs调用命令行使用nodejs读写文件添加jwtexpress上传文件基于express在nodejs中读取和编辑html文件环境我们稍微说一下。起初,wget爬取网站,寻找一些可视化的工具来达到目的。后来在搜索的过程中,看到wget可以实现全站的爬取,好简单,怎么做到的!#抓取整个站点wget-r-p-np-k-Ehttp://www.xxx.com#w抓取第一层wget-l1-p-np-khttp://www.xxx.com-r递归爬行-k爬行后修正链接,适合本地浏览-erobots=off忽略robots协议,强制爬行(流氓爬行)-E将text/html类型文档保存为.html文件,以供使用基于Python的翻译tool在github上找了好几个工具,也考虑过用官方的API(微软和谷歌都有提供),最后还是用soimort/translate-shell(不想花钱和时间再看文档>w<)这个transshell工具提供了几个翻译源(google、bing、yandex、apertium)。不知道为什么只能用googleΣ(!?д?)。Google也很有保障,问题不大。安装并不复杂,只需要安装gawk即可,其他在ubuntu系统中默认包含:GNUAwkhawk安装$sudoapt-getinstallgawk试试:$gawk-f<(curl-Lsgit.io/translate)---外壳安装反式车身。官方文档提供了三种方法。方法一不知道为什么会有bug。方法2不是很熟悉。最后选择方法三:$gitclonehttps://github.com/soimort/translate-shell$cdtranslate-shell/$make$[sudo]makeinstall也好用:$trans'Saluton,Mondo!'Saluton,Mondo!Hello,World!翻译Saluton,Mondo![世界语->英语]世界!短输出方式:$trans-brief'Saluton,Mondo!'你好世界!翻译文件:$trans-ben:zh-iinput.txt-ooutput.txt使用trans调用googletranslate进行翻译不能频繁调用。频繁调用后,后续请求会是503,请求会被谷歌限制!!在使用nodejs调用命令行完成翻译研究后,感觉本地实现翻译需要安装各种东西,还是做成web应用比较好。使用express快速搭建网站应用。nodejs下调用命令其实一点头绪都没有。搜索结果发现可以使用ChildProcess模块??来实现:constutil=require('util')constexec=util.promisify(require('child_process').exec)exec(`trans-V`).then(({stdout,stderr})=>{if(stdout.indexOf("notinstalled")>-1)returnError(stdout)}).then(()=>exec(`trans-b${language}-i${input}-o${output}`)).then(({stdout,stderr})=>{return{input,output,message:stdout}})使用nodejs读写文件不会描述的很详细,只是简单罗列一下用到的函数:fs.readFileSync(path)同步读取文件例子:constdata=fs.readFileSync('./test.txt')console.log(data.toString())//testing!fs.writeFileSync(path,data)同步写入文件示例:try{fs.writeFileSync('./test.txt','testing!!')}catch(e){console.error(e)}fs.unlinkSync(path)同步删除文件例子:try{fs.unlinkSync('./test.txt')}catch(e){console.error(e)}添加jwtforexpress先说jwt,全称是JSONWebTokens,这是一种开放的、行业标准的RFC7519方法,用于表示两端之间的应用程序安全性。RFC是由互联网协会(ISOC)发起的互联网通信协议规范,它包括了多种协议,以及互联网上新开发的协议和开发中的所有记录。jwt的实现已经成为互联网通信安全标准,那么在express中如何实现呢?首先安装以下两个包:auth0/node-jsonwebtokenauth0/express-jwtnpmi-Sexpress-jwtjsonwebtoken使用:const{router}=require('express')constdecode_jwt=require('express-jwt')constjwt=require('jsonwebtoken')constsecret="your-secret"//salt//loginrouter.get('/login',function(req,res,next){/**+[登录逻辑]...**/consttoken=jwt.sign(user,secret)res.status(200).send({user,token})})//受限接口router.get('/user/star',decode_jwt({secret:secret}),(req,res)=>{const{user}=reqconststars=[]/**+[获取用户星级列表]**/res.status(200).send(stars)})解释,使用jsonwebtoken包进行加密,secret作为salt对内容进行混淆(为了安全,不能泄露给客户端),然后通过express-jwt解密处理http头中的授权:Bearer[token]中的token获取用户信息。这样就可以在/user/star接口中获取到用户信息,用于后续的业务处理。基于express上传文件,忘记注明这里所说的express版本是4,所以在新版本的express4文档中,对上传文件的处理有说明:在Express4中,req.files是默认情况下不再适用于req对象。要访问req.files对象上的上传文件,请使用多部分处理中间件,如busboy、multer、formidable、multiparty、connect-multiparty或pez。意思是:express4版本的req.files字段不再有效,需要使用上面提到的中间件来提供读取上传文件的支持。看了文档,最终还是选择了multer。使用方法如下:安装npmi-Smulter使用constmulter=require('multer')constlimits={fieldSize:1024*1024*3}constextname='html'//创建本地存储conststorage=multer.diskStorage({destination:function(req,file,cb){cb(null,'./uploads');},//存储文件时自定义文件名filename:function(req,file,cb){cb(null,file.fieldname+'-'+Date.now());}})//创建上传处理constuploader=require('multer')({storage,limits,fileFilter(req,file,cb){if(path.extname(file.originalname)===`.${extname}`)cb(null,true)elsecb(newError(`uploadfileextnamemustbe${extname}`))}})/***上传接口*只接受http头为`content-type:multipart/form-data`的数据*这里将获取字段的内容设置为`file`并存储为文件完成文件上传**/router.post('/trans_on_upload',uploader.single('file'),(req,res)=>{const{file}=reqconstfileData=fs.readFileSync(file.path)console.log(fileData.toString())res.status(200)})multer接受多个文件上传方式:uploader.single(fieldname)接受以fieldname命名的文件。有关此文件的信息存储在req.fileuploader.array(fieldname[,maxCount])中,接受由fieldname命名的文件数组。maxCount可以配置为限制最大上传数量。有关这些文件的信息保存在req.files中。uploader.fields(fields)接受具有指定字段的混合文件。有关这些文件的信息保存在req.files中。fields应该是一个对象数组,并且应该有name和可选的maxCount属性。示例:[{name:'avatar',maxCount:1},{name:'gallery',maxCount:8}]uploader.none()只接受文本字段。如果任何文件上传到此模式,将发生“LIMIT_UNEXPECTED_FILE”错误。这与upload.fields([])具有相同的效果。uploader.any()接受任何上传的文件。文件数组将保存在req.files中。警告:确保您始终处理用户文件上传。永远不要将multer用作全局中间件,因为恶意用户可以将文件上传到您没有预料到的路由,并且应该只在您需要处理上传文件的路由上使用。multer的使用有一定的局限性,并不是所有项目都适合使用,所以不做深入说明。nodejs环境下读取和编辑html文件这里的过程是使用fs.readFileSync(path)读取html文件的内容,希望以DOM方式编辑内容,在jsdom/jsdom中进行处理与浏览器相同的方式DOM是一个非常有用的工具。比如我的需求是获取所有TextNode提取的内容,翻译替换原来的内容,最后导出html内容:const{JSDOM}=require("jsdom")const{minify}=require("html-minifier")//递归获取所有TextNodeconstgetAllTextNode=(node)=>{varall=[];对于(node=node.firstChild;node;node=node.nextSibling){const{parentNode}=nodeif(node.nodeType==3){all.push(node)}elseall=all.concat(getAllTextNode(node));}返回全部;}consthtml=""/**+[获取html内容]**/constvbrows=newJSDOM(minify(html,{collapseWhitespace:true}))const{document}=vbrows.windowconsttextNodes=getAllTextNode(document.body)textNodes.forEach(textNodes=>{consttransStr=textNodes.textContent/**翻译处理**/textNodes.textContent=transStr})//翻译结果console.log('transresult',vbrows.serialize())总结完成一个应用的范围其实挺广的,如果讨论的内容比较深入,应该多写一些内容。由于手头还有其他工作,所以只能粗略记录下关键字和使用方式,以及原理方向,等有时间再深入研究。