用JS搞了一個自動翻譯,從此不再頭疼看英文書了

gavin103發表於2018-05-21

小記:作為一個有追求的碼農,“懶”,不一定是一個貶義詞。有時候“懶”,才是進步的動力!

背景

經常遇到這樣的情況,發現一本眼饞的技術書?,卻發現只有英文版。慢慢啃嗎?真的很痛苦。於是靈光一閃,我需要這樣一個小工具,點選執行可以批量的完成翻譯任務。於是,去吧皮卡丘!

技術選型

  • 翻譯一直信任某歌(科學上網);
  • 作為一名小前端,希望用JS一桶天下;

辛路例程

嘗試一:

用某歌翻譯的API,翻山越嶺,翻江倒海的查到了API的用法,確實很好用。但是在嘗試過程中發現,還需要VISA註冊。於是撲街?!

嘗試二:

用cheerio做個爬蟲?做了一半才想起來,翻譯出的資料是JS嵌入的,cheerio是無法抓取到的,被自己蠢哭?!

嘗試三:

祭出大招,使用無頭瀏覽器,模擬人工翻譯過程,啥過程?英文輸入->翻譯->將中文輸入拷貝到指定文件?。

Show Me the CODE!

const puppeteer = require('puppeteer');
const path = require('path');
const fs = require('fs');
const util = require('util');

const appendFile = util.promisify(fs.appendFile);

const CONFIG = {
    input: 'React/ch09.txt',
    out:'out.txt',
    url: 'https://translate.google.cn/#en/zh-CN/'
};

const inputPath = path.join(__dirname,CONFIG.input);
const outPath = path.join(__dirname,CONFIG.out);

const trans = async ()=>{
    try {
        //開啟瀏覽器,進入谷歌翻譯網頁
        const browser = await puppeteer.launch({headless: false});
        const page = await browser.newPage();
        await page.goto(CONFIG.url);

        fs.writeFileSync(outPath,'');
        //讀取文件
        let fr = fs.readFileSync(inputPath,"utf-8");
        let tmpArr = [];
        fr.split('\n').forEach((line,index)=>{
            let tmp = line.trim();
            tmp.length > 0 && tmpArr.push(' '+tmp)
        });

        for(let i=0; i<tmpArr.length; i++){
            let tmpInput = tmpArr[i];
            await page.type('#source', tmpInput,{delay: 10});
            page.click('#src-translit');
            await page.waitFor(1500);
            let transOutput = await page.evaluate(() => {
                let text='';
                if(document.querySelector('#result_box span')){
                    [...document.querySelectorAll('#result_box span')].forEach((nod)=>{
                        text+=nod.innerText;
                    })
                }
                return text;
            });
            console.log(i,tmpInput);
            await appendFile(outPath,tmpInput+'\n');
            await appendFile(outPath,transOutput+'\n');
            await page.waitFor(500);
            page.click('#gt-clear');
        }
        await page.waitFor(1000);
        browser.close();
    }catch (e) {
        console.log(e);
    }

};

trans();

複製程式碼

娓娓道來

  • 無頭瀏覽器選用的是puppeteer,因為想接觸一下這個PhantomJS的繼承者。
  • 作為指令碼執行在node環境中,當然充分利用Node的原生API了(fs,util,path)。
  • 使用了async/await, 讓非同步程式碼看著更優雅一點。
  • 將非同步的fs.appendFile Promise化。
  • Puppeteer的API,就簡單用了幾個:
    • puppeteer.launch 開啟瀏覽器
    • browser.newPage 新建頁面
    • page.goto 跳轉到制定網址
    • page.type 模擬使用者輸入
    • page.click 模擬點選事件,引數為被點選元素的選擇器
    • page.waitFor 等待,為什麼要等待?JS單執行緒,你懂得,慢,拖拉機一樣慢!
    • browser.close 關閉瀏覽器,點選紅叉退出。
    • 最重要的就是page.evaluate了,通過回撥函式,輕鬆操作返回頁面的dom。

大概就這些,第一次發文,歡迎各位過路大神拍磚。

附git地址:https://github.com/gavin103/gotrans

後續將繼續改進,敬請期待~

相關文章