Google пропонує API перекладу Google із структурою витрат на основі використання як частину своєї Google Cloud. Існує також недокументований API, який можна використовувати без ключа , але який відмовляється працювати лише після кількох запитів. При використанні функції перекладу веб-сайтів Google Chrome помітно, що сторінки можна перекладати в дуже хорошій якості без будь-яких помітних обмежень.
Очевидно, тут вже використовується вдосконалена модель nmt . Але який API використовує Google Chrome внутрішньо для перекладу вмісту і чи може цей API також адресуватися безпосередньо - навіть на стороні сервера? Для аналізу мережевого трафіку рекомендуються такі інструменти, як Wireshark або Telerik Fiddler , які також можуть аналізувати зашифрований трафік. Але Chrome навіть безкоштовно надсилає запити на переклад сторінки: їх можна легко переглянути за допомогою Chrome DevTools:
Якщо ви виконуєте переклад, то перейміть важливий запит POST на https://translate.googleapis.com за допомогою "Копіювати> Копіювати як cURL (bash)" і виконайте його в такому інструменті, як Поштовець , наприклад, ви можете відправити запит знову без проблем:
Значення параметрів URL-адреси також багато в чому очевидне:
Ключ | Приклад значення | Значення |
ано | 3 | Режим анотацій (впливає на формат повернення) |
клієнт | te_lib | Інформація про клієнта (змінюється, значення "webapp" через веб-інтерфейс Google Translate; впливає на формат повернення та обмеження швидкості) |
формат | html | Формат рядка (важливий для перекладу тегів HTML) |
v | 1.0 | Номер версії Google Translate |
ключ | AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw | Ключ API (див. Нижче) |
logld | vTE_20200210_00 | Версія протоколу |
сл | де | Мова-джерело |
tl | en | Мова перекладу |
sp | nmt | Модель ML |
tc | 1 | невідомо |
сер | 1 | невідомо |
tk | 709408.812158 | Токен (див. Нижче) |
Мода | 1 | невідомо |
Деякі заголовки запитів також встановлюються, але їх переважно можна ігнорувати. Після ручного скасування вибору всіх заголовків, включаючи заголовки з агента користувача , виявляється проблема з кодуванням при введенні спеціальних символів (тут при перекладі " Hello World "):
Якщо ви повторно активуєте користувальницький агент (який, як правило, не завдає шкоди), API надає кодовані символи UTF-8:
Ми вже там і чи маємо всю інформацію для використання цього API поза Google Chrome? Якщо ви змінили рядок для перекладу (поле даних q запиту POST), наприклад, з «Hello world» на «Hello world ! “, Ми отримуємо повідомлення про помилку:
Тепер ми знову перекладаємо цей модифікований у Google Chrome за допомогою функції перекладу веб-сайтів і виявляємо, що, крім параметра q , параметр tk також змінився (всі інші параметри залишились незмінними):
Очевидно, це маркер, який залежить від рядка, структуру якого непросто побачити. Коли ви починаєте переклад веб-сайту, завантажуються такі файли:
- 1 файл CSS: translateelement.css
- 4 графіки: translate_24dp.png (2x), gen204 (2x)
- 2 файли JS: main_de.js , element_main.js
Два файли JavaScript затуманені та зменшені. Такі інструменти, як JS Nice та de4js , тепер допомагають нам зробити ці файли більш читабельними. Для їх налагодження в реальному часі ми рекомендуємо розширення Chrome Requestly, яке на ходу тунелює локальні віддалені файли:
Тепер ми можемо налагодити код ( CORS спочатку потрібно активувати на локальному сервері). Відповідний розділ коду для генерації маркера схований у цьому розділі у файлі element_main.js:
b7739bf50b2edcf636c43a8f8910def9
Тут текст хешується за допомогою деяких бітових зрушень . Але, на жаль, нам все ще бракує однієї частини головоломки: окрім аргументу a (а саме тексту, що перекладається), ще один аргумент b передається функції Bp () - свого роду насіння, яке, здається, час від часу змінюється і яке також включає перетікає в хешування. Але звідки він? Якщо перейти до виклику функції Bp () , ми знайдемо наступний розділ коду:
b7739bf50b2edcf636c43a8f8910def9
Функція Hq оголошується заздалегідь наступним чином:
b7739bf50b2edcf636c43a8f8910def9
Тут Deobfuscater залишив трохи сміття; Після того, як ми замінили String.fromCharCode ('...') на відповідні рядки символів, видалимо застарілий a () та складемо разом виклики функції [c (), c ()] , результат буде:
b7739bf50b2edcf636c43a8f8910def9
Або навіть простіше:
b7739bf50b2edcf636c43a8f8910def9
Функція yq попередньо визначалася як:
b7739bf50b2edcf636c43a8f8910def9
Здається, насіння знаходиться в глобальному об’єкті google.translate._const._ctkk , який доступний під час виконання. Але де це встановлено? В іншому, раніше завантаженому файлі JS main_de.js, принаймні він також доступний на початку. На початку додаємо наступне:
b7739bf50b2edcf636c43a8f8910def9
У консолі ми фактично отримуємо поточне насіння:
Це залишає сам Google Chrome, який, очевидно, надає насіння, як останній варіант. На щастя, його вихідний код (Chromium, включаючи компонент Translate) є відкритим і тому є загальнодоступним. Ми витягуємо сховище локально і знаходимо виклик функції TranslateScript :: GetTranslateScriptURL у файлі translate_script.cc у папці components / translate / core / browser:
b7739bf50b2edcf636c43a8f8910def9
Змінна з URL-адресою чітко визначена в тому ж файлі:
b7739bf50b2edcf636c43a8f8910def9
Якщо ми зараз уважніше розглянемо файл element.js (після повторної деобфускації), ми виявимо жорсткий запис c._ctkk - об'єкт google.translate також встановлюється відповідно і запускається завантаження всіх відповідних активів (які ми вже виявили раніше):
b7739bf50b2edcf636c43a8f8910def9
Тепер ключ параметра залишається для розгляду (зі значенням AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw). Здається, це загальний ключ API браузера (який також можна знайти в деяких результатах Google ). Він встановлюється в Chromium у файлі translate_url_util.cc у папці components / translate / core / browser:
b7739bf50b2edcf636c43a8f8910def9
Ключ генерується в google_apis / google_api_keys.cc із фіктивного значення:
b7739bf50b2edcf636c43a8f8910def9
Однак тест показує, що виклики API працюють однаково без цього ключового параметра. Якщо ви експериментуєте з API, ви отримаєте код стану 200, якщо успішно. Якщо після цього ви натрапите на ліміт, ви отримаєте код стану 411 із повідомленням " Запити POST вимагають заголовка довжини вмісту ". Тому доцільно включити цей заголовок (який автоматично встановлюється як тимчасовий заголовок у Поштовику).
Формат повернення перекладених рядків є незвичним, коли в одному запиті є кілька речень. Окремі речення укладені тегами i- / b-HTML:
Крім того, Google Chrome не надсилає повний HTML до API, але зберігає значення атрибутів, такі як href, у запиті (і замість цього встановлює індекси, щоб теги можна було потім призначити на стороні клієнта):
Якщо ви змінили значення клієнта ключа POST з te_lib (Google Chrome) на webapp ( веб-сайт Google Translate ) ви отримуєте остаточний перекладений рядок:
Проблема полягає в тому, що ви набагато більше шансів нарватися на обмеження швидкості , ніж через te_lib (для порівняння: з веб - додаток це досягається після 40000 символів, з te_lib немає обмеження швидкості). Тому нам слід уважніше розглянути, як Chrome аналізує результат. Ми знайдемо його тут у елементі_main.js:
b7739bf50b2edcf636c43a8f8910def9
Якщо ви надсилаєте весь HTML-код до API, він залишає атрибути в перекладеній відповіді. Тому нам не потрібно повністю імітувати поведінку аналізу, а лише витягувати остаточний перекладений рядок із відповіді. Для цього ми створюємо невеликий аналізатор тегів HTML, який відкидає найвіддаленіші теги <i>, включаючи їх вміст, і видаляє крайні теги <b>. З цими знаннями ми можемо тепер (після встановлення залежностей за допомогою composer вимагає fzaninotto / faker vielhuber / stringhelper ) створити серверну версію API перекладу:
b7739bf50b2edcf636c43a8f8910def9
Нижче наведено результати первинного тесту, проведеного на п’яти різних системах з різною пропускною здатністю та IP-адресами:
Характер | Символів на запит | Тривалість | Частота помилок | Вартість через офіційний API |
13.064.662 | ~250 | 03: 36: 17 год | 0% | 237,78€ |
24.530.510 | ~250 | 11: 09: 13 год | 0% | 446,46€ |
49.060.211 | ~250 | 20: 39: 10 год | 0% | 892,90€ |
99.074.487 | ~1000 | 61: 24: 37 год | 0% | 1803,16€ |
99.072.896 | ~1000 | 62: 22: 20 год | 0% | 1803,13€ |
Σ284.802.766 | ~ Ø550 | Σ159: 11: 37 год | 0% | Σ € 5183,41 |
Примітка: Цей допис у блозі, що включає всі сценарії, написаний лише для тестування. Не використовуйте сценарії для продуктивного використання, а НЕ працювати з офіційним API Google Translation .