作這個記錄以前,剛完成使用drone做爲公司前端項目的持續交付工具的實踐,打算寫的教程前先把官方文檔扒下來作個翻譯站。在實踐一番後,卡在不能頻密調取google翻譯這塊上,項目沒法進行下去。最後以爲經歷的過程涉及的內容挺多的因此記錄一下同時分享給你們。html
此次經歷涉及如下知識:前端
wget
抓取網站python
的翻譯工具nodejs
調取命令行nodejs
讀寫文件express
添加jwt
express
實現上傳文件nodejs
環境下讀取並編輯html文件咱們一點點來講。node
wget
抓取網站最初是尋找有什麼帶可視化的工具來達到目的的,後來在尋找的過程當中看到原來wget
能實現整站抓取,因此怎樣簡單怎樣來!python
# 抓取整站 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<)git
這個trans shell
工具提供幾個翻譯源(google, bing, yandex, apertium),不知道爲什麼能用的只有google Σ(!゚д゚)。google也頗有保證了,問題不大。github
安裝並不複雜,只須要安裝gawk
,其餘在ubuntu系統下默認都有包含的:web
gawk安裝shell
$ sudo apt-get install gawk
嘗試:express
$ gawk -f <(curl -Ls git.io/translate) -- -shell
安裝trans本體,官方文檔提供三種方式,方式1
不知道爲什麼有bug,方式2
並不太熟悉,最後選擇方式3
:npm
$ 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
怎樣實現?
首先安裝下面兩個包:
npm 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: 1024*1024*3 } 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
使用起來有必定限制,並非全部項目合適使用,因此不作深刻說明。
nodejs
環境下讀取並編輯html文件這裏處理的流程是使用fs.readFileSync(path)
讀取html文件內容後,但願能以dom方式編輯內容,使用jsdom/jsdom
能像在瀏覽器同樣的方式處理DOM,是很是好用的工具。
好比個人需求是獲取全部TextNode
提取內容進行翻譯並替換原來內容,最後導出html內容:
const { JSDOM } = require("jsdom") const { minify } = require("html-minifier") //遞歸得到全部TextNode const 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.window const textNodes = getAllTextNode(document.body) textNodes.forEach(textNodes=>{ const transStr = textNodes.textContent /**翻譯處理**/ textNodes.textContent = transStr }) //翻譯結果 console.log('trans result', vbrows.serialize())
完成一個應用涉及的範圍其實挺廣的,內容若是再深刻討論應該能寫更多內容吧。因爲手上還有其餘工做,只能大體記錄關鍵詞和使用的方式,原理方向等有時間再深刻研究。