做这个记录之前,刚完成使用drone作为公司前端项目的持续交付工具的实践,打算写的教程前先把官方文档扒下来做个翻译站。在实践一番后,卡在不能频密调取google翻译这块上,项目无法进行下去。最后觉得经历的过程涉及的内容挺多的所以记录一下同时分享给大家。这次经历涉及以下知识:wget抓取网站使用基于python的翻译工具使用nodejs调取命令行使用nodejs读写文件为express添加jwt基于express实现上传文件在nodejs环境下读取并编辑html文件我们一点点来说。wget抓取网站最初是寻找有什么带可视化的工具来达到目的的,后来在寻找的过程中看到原来wget能实现整站抓取,所以怎样简单怎样来!# 抓取整站wget -r -p -np -k -E http://www.xxx.com# w抓取第一级wget -l 1 -p -np -k http://www.xxx.com-r 递归抓取-k 抓取后修正链接,适合本地浏览-e robots=off 忽略robots协议,强制抓取(流氓抓取)-E 将text/html类型的文档保存为.html的文件使用基于python的翻译工具这个在github上找了几个工具,同时也考虑过使用官方提供的API(微软和google均有提供),最后得出使用soimort/translate-shell(并不想花钱和花时间再看文档上了>w<)这个trans shell工具提供几个翻译源(google, bing, yandex, apertium),不知道为何能用的只有google (!゚゚)。google也很有保证了,问题不大。安装并不复杂,只需要安装gawk,其他在ubuntu系统下默认都有包含的:GNU Awkgawk安装$ sudo apt-get install gawk尝试:$ gawk -f <(curl -Ls git.io/translate) – -shell安装trans本体,官方文档提供三种方式,方式1不知道为何有bug,方式2并不太熟悉,最后选择方式3:$ git clone https://github.com/soimort/translate-shell$ cd translate-shell/$ make$ [sudo] make install使用起来也是简单:$ trans ‘Saluton, Mondo!‘Saluton, Mondo!Hello, World!Translations of Saluton, Mondo![ Esperanto -> English ]Saluton , Hello,Mondo ! World!简短输出方式:$ trans -brief ‘Saluton, Mondo!‘Hello, World!翻译文件:$ trans -b en:zh -i input.txt -o output.txt使用trans调取google translate进行翻译不能频频调用,频频调用之后会令后续请求503,被google限制请求!!使用nodejs调取命令行完成翻译的调研后,感觉本地实现翻译需要安装各种东西,不如做成web应用好了。用express快速建立网站应用,关于在nodejs下调用命令其实是没啥头绪的,搜索得出结果发现可以使用Child Process模块实现:const util = require(‘util’)const exec = util.promisify(require(‘child_process’).exec)exec(trans -V) .then(({stdout, stderr}) => { if(stdout.indexOf(“not installed”) > -1) return Error(stdout) }) .then(()=>exec(trans -b ${language} -i ${input} -o ${output})) .then(({stdout, stderr})=>{ return { input, output, message: stdout } })使用nodejs读写文件这个就不详细说明了,简单列一下用到的函数:fs.readFileSync(path)同步读取文件例子:const data = 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)}为express添加jwt先说一下jwt,全名叫JSON Web Tokens,是一种开放的,行业标准的RFC 7519方法,用于表示两端之间的应用安全。RFC是由Internet Society(ISOC)赞助发行的互联网通信协议规范,包含各种各样的协议,同时包含互联网新开发的协议及发展中所有的记录。jwt这种实现已经成为互联网通讯安全标准,那么在express怎样实现?首先安装下面两个包:auth0/node-jsonwebtokenauth0/express-jwtnpm i -S express-jwt jsonwebtoken使用:const { router } = require(’express’)const decode_jwt = require(’express-jwt’)const jwt = require(‘jsonwebtoken’)const secret = “your-secret” //盐// 登录router.get(’/login’, function(req, res, next) { /+[登录逻辑]…/ const token = jwt.sign(user, secret) res.status(200).send({ user, token })})//受限的接口router.get(’/user/star’, decode_jwt({secret: secret}), (req, res)=>{ const { user } = req const stars = [] /+[获取用户star列表]/ res.status(200).send(stars)})解释一下,jsonwebtoken包为加密作用, secret作为盐用来混淆内容(出于安全是不能对客户端公开),然后经过express-jwt解密处理http header里带有的authorization: Bearer [token]中的token来获得user信息。这样在/user/star接口中就能获取到用户资料做后续的业务处理了。基于express实现上传文件忘了说明这里提及的express版本为4,那么在新版的express 4文档中提及了这么一段关于上传文件的处理说明:In Express 4, req.files is no longer available on the req object by default. To access uploaded files on the req.files object, use multipart-handling middleware like busboy, multer, formidable, multiparty, connect-multiparty, or pez.意思是:express 4 版本req.files字段不在有效,需要使用上面提及的中间件提供支持才能实现读取上传来的文件。看了一番文档,最后选择了multer。下面讲一下如何使用:安装npm i -S multer使用const multer = require(‘multer’)const limits = { fieldSize: 102410243 }const extname = ‘html’//创建本地储存const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, ‘./uploads’); }, //储存文件时自定义文件名称 filename: function (req, file, cb) { cb(null, file.fieldname + ‘-’ + Date.now()); }})//创建上传处理const uploader = require(‘multer’)({ storage, limits, fileFilter(req, file, cb){ if(path.extname(file.originalname) === .${extname}) cb(null, true) else cb(new Error(upload file extname must be ${extname})) }})/** * 上传接口 * 只接受http头是content-type: multipart/form-data的数据 * 这里设定获取字段是file的内容储存成文件来完成文件上传工作 /router.post(’/trans_on_upload’, uploader.single(‘file’), (req, res)=>{ const { file } = req const fileData = 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) 接受指定 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”)//递归获得所有TextNodeconst getAllTextNode = (node)=>{ var all = []; for (node=node.firstChild;node;node=node.nextSibling){ const { parentNode } = node if (node.nodeType==3){ all.push(node) } else all = all.concat(getAllTextNode(node)); } return all;}const html = “”/+[获取html内容]**/const vbrows = new JSDOM(minify(html, { collapseWhitespace: true}))const { document } = vbrows.windowconst textNodes = getAllTextNode(document.body)textNodes.forEach(textNodes=>{ const transStr = textNodes.textContent /翻译处理/ textNodes.textContent = transStr})//翻译结果console.log(’trans result’, vbrows.serialize())总结完成一个应用涉及的范围其实挺广的,内容如果再深入讨论应该能写更多内容吧。由于手上还有其他工作,只能大致记录关键词和使用的方式,原理方向等有时间再深入研究。
...