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 | Информация о клиенте (различается; в веб-интерфейсе Google Translate значение равно "webapp"; влияет на формат возвращаемого значения и ограничение скорости запросов). |
| формат | 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
Деобфускатор оставил здесь какой-то мусор; после того, как мы заменили 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-запросы требуют заголовка Content-length ». Поэтому рекомендуется также включать этот заголовок (который автоматически устанавливается как временный заголовок в 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 .