forked from KaKi87/deepl-scraper
100 lines
3.4 KiB
JavaScript
100 lines
3.4 KiB
JavaScript
const
|
|
puppeteer = require('puppeteer'),
|
|
axios = require('axios'),
|
|
homepage = 'https://www.deepl.com/translator';
|
|
|
|
let browser;
|
|
|
|
const getBrowser = async () => {
|
|
if(browser) return browser;
|
|
browser = await puppeteer.launch({ args: ['--window-size=1920,1080'] });
|
|
browser.on('disconnected', () => browser = null);
|
|
return browser;
|
|
};
|
|
|
|
const getNewPage = async () => await (await getBrowser()).newPage();
|
|
|
|
module.exports = {
|
|
translate: async (sentence, sourceLanguage = 'auto', targetLanguage) => {
|
|
if(!/^(auto|[a-z]{2})$/.test(sourceLanguage))
|
|
throw new Error('INVALID_SOURCE_LANGUAGE');
|
|
if(!/^[a-z]{2}-[A-Z]{2}$/.test(targetLanguage))
|
|
throw new Error('INVALID_TARGET_LANGUAGE');
|
|
|
|
const
|
|
sourceLangSelect = '.lmt__language_select--source button',
|
|
targetLangSelect = '.lmt__language_select--target button',
|
|
sourceLangMenu = '.lmt__language_select__menu_source',
|
|
targetLangMenu = '.lmt__language_select__menu_target',
|
|
sourceLangButton = `${sourceLangMenu} [dl-test=translator-lang-option-${sourceLanguage}]`,
|
|
targetLangButton = `${targetLangMenu} [dl-test=translator-lang-option-${targetLanguage}]`,
|
|
originalSentenceField = '.lmt__source_textarea',
|
|
targetSentenceField = '.lmt__target_textarea'/*,
|
|
targetSentencesContainer = '.lmt__translations_as_text'*/;
|
|
|
|
const page = await getNewPage();
|
|
|
|
await page.goto(homepage);
|
|
await page.click(sourceLangSelect);
|
|
await page.waitForSelector(sourceLangMenu, { visible: true });
|
|
try {
|
|
await page.click(sourceLangButton);
|
|
}
|
|
catch(_){
|
|
throw new Error('UNSUPPORTED_SOURCE_LANGUAGE');
|
|
}
|
|
await page.waitForSelector(sourceLangMenu, { hidden: true });
|
|
|
|
await page.click(targetLangSelect);
|
|
await page.waitForSelector(targetLangMenu, { visible: true });
|
|
try {
|
|
await page.click(targetLangButton);
|
|
}
|
|
catch(_){
|
|
throw new Error('UNSUPPORTED_TARGET_LANGUAGE');
|
|
}
|
|
await page.waitForSelector(targetLangMenu, { hidden: true });
|
|
|
|
await page.waitForSelector(originalSentenceField);
|
|
await page.type(originalSentenceField, sentence);
|
|
|
|
let sentences = [];
|
|
let _res = {};
|
|
page.on('requestfinished', request => request.response().json().then(res => {
|
|
if(!res['result']) return;
|
|
sentences.push(...res['result']['translations'][0]['beams'].map(item => ({
|
|
value: item['postprocessed_sentence'],
|
|
confidence: item['totalLogProb']
|
|
})));
|
|
_res = {
|
|
source: {
|
|
lang: res['result']['source_lang'].toLowerCase(),
|
|
...(sourceLanguage === 'auto' ? {
|
|
confident: !!res['result']['source_lang_is_confident']
|
|
} : {}),
|
|
sentence
|
|
},
|
|
target: {
|
|
lang: res['result']['target_lang'].toLowerCase(),
|
|
sentences: sentences.sort((a, b) => a.confidence - b.confidence).map(item => item.value)
|
|
}
|
|
};
|
|
}).catch(() => {}));
|
|
await page.waitForSelector('.lmt--active_translation_request');
|
|
await page.waitForSelector('.lmt--active_translation_request', { hidden: true });
|
|
_res.target.translation = await page.$eval(targetSentenceField, el => el.value);
|
|
page.close().catch(() => {});
|
|
return _res;
|
|
},
|
|
quit: async () => {
|
|
if(browser)
|
|
await browser.close();
|
|
},
|
|
getSupportedLanguages: async () => {
|
|
const { data } = await axios.get(homepage);
|
|
return {
|
|
sourceLanguages: [...data.matchAll(/selectLang\.source\.([a-z]{2})/g)].map(match => match[1]),
|
|
targetLanguages: [...data.matchAll(/translator\/selectLang\.target\.(?:([a-z]{2})'|[a-z]{2}\.([a-z]{2}-[A-Z]{2}))/g)].map(match => match[2] || `${match[1]}-${match[1].toUpperCase()}`)
|
|
};
|
|
}
|
|
};
|