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)» и выполняете его в таком инструменте, как Postman , например, вы можете отправить запрос снова без проблем.:

Значение параметров URL также во многом очевидно:
Ключ | Пример значения | Имея в виду |
анно | 3 | Режим аннотации (влияет на формат возврата) |
клиент | te_lib | Информация о клиенте (варьируется, значение - "webapp" через веб-интерфейс Google Translate; влияет на формат возврата и ограничение скорости) |
формат | html | Формат строки (важно для перевода HTML-тегов) |
v | 1.0 | Номер версии Google Translate |
ключ | AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw | Ключ API (см. Ниже) |
logld | vTE_20200210_00 | Версия протокола |
сл | де | Язык источника |
tl | en | Язык перевода |
зр | нмт | ML модель |
tc | 1 | неизвестно |
SR | 1 | неизвестно |
тк | 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 , который туннелирует удаленные файлы локально на лету.:

Теперь мы можем отладить код (сначала нужно активировать 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-запросы требуют заголовка длины содержимого ». Поэтому рекомендуется включить этот заголовок (который автоматически устанавливается в качестве временного заголовка в Postman).
Формат возврата переведенных строк необычен, когда в одном запросе содержится несколько предложений. Отдельные предложения заключены в теги i- / b-HTML.:

Кроме того, Google Chrome не отправляет весь HTML-код в API, но сохраняет значения атрибутов, такие как href, в запросе (и вместо этого устанавливает индексы, чтобы теги могли позже быть назначены на стороне клиента):

Если вы измените значение клиента ключа POST из te_lib (Google Chrome) в webapp ( веб-сайт Google Translation ) вы получите окончательную переведенную строку:

Проблема в том, что у вас гораздо больше шансов столкнуться с ограничением скорости, чем через te_lib (для сравнения: с webapp это достигается после 40 000 символов, с te_lib ограничения скорости нет). Поэтому нам нужно внимательнее взглянуть на то, как Chrome анализирует результат. Мы найдем его здесь, в element_main.js:
b7739bf50b2edcf636c43a8f8910def9
Если вы отправляете весь HTML-код в API, он оставляет атрибуты в переведенном ответе. Поэтому нам не нужно имитировать все поведение синтаксического анализа, а только извлекать последнюю переведенную строку из ответа. Для этого мы создаем небольшой синтаксический анализатор тегов HTML, который отбрасывает самые внешние теги <i>, включая их содержимое, и удаляет самые внешние теги <b>. Обладая этими знаниями (после установки зависимостей с помощью composer require 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 .