web-dev-qa-db-fra.com

API TTS Google Translate bloquée

Google a mis en place un captcha pour empêcher les gens d'accéder à l'API de traduction TTS https://translate.google.com/translate_tts?ie=UTF-8&q=test&tl=zh-TW . Je l'utilisais dans mon application mobile. Maintenant, il ne retourne rien. Comment contourner le captcha?

21
ginsengtang

Ajoutez le qualificatif '& client = tw-ob' à la fin de votre requête. https://translate.google.com/translate_tts?ie=UTF-8&q=test&tl=zh-TW&client=tw-ob

Cette réponse ne fonctionne plus de manière cohérente. Votre adresse IP sera temporairement bloquée par Google si vous en abusez trop.

23
ginsengtang

il y a 3 problèmes principaux:

  1. vous devez inclure "client" dans votre chaîne de requête (client = t semble fonctionner).
  2. (dans le cas où vous essayez de le récupérer à l'aide d'AJAX), le référent de la demande HTTP doit être https://translate.google.com/
  3. Le champ "tk" change pour chaque requête, et il doit être rempli avec un hachage correspondant: tk = hash (q, TKK), où q est le texte à TTSer, et TKK est un var dans la portée globale lorsque vous chargez la traduction .google.com: (tapez "window.TKK" dans la console). voir la fonction de hachage au bas de cette réponse (calcHash).

résumer:

function generateGoogleTTSLink(q, tl, tkk) {
    var tk = calcHash(q, tkk);
    return `https://translate.google.com/translate_tts?ie=UTF-8&total=1&idx=0&client=t&ttsspeed=1&tl=${tl}&tk=${tk}&q=${q}&textlen=${q.length}`;
}

generateGoogleTTSLink('ciao', 'it', '410353.1336369826');
// see definition of "calcHash" in the bottom of this comment.

=> pour mettre la main sur un TKK, vous pouvez ouvrir le site Web Google Translate, puis taper "TKK" dans la console des outils de développement (par exemple: "410353.1336369826").

REMARQUE: la valeur TKK change toutes les heures, et donc, les anciens TKK peuvent être bloqués à un moment donné, et leur rafraîchissement peut être nécessaire (bien que jusqu'à présent, il semble que les anciennes clés puissent fonctionner pendant longtemps).

si vous souhaitez actualiser périodiquement TKK, il peut être automatisé assez facilement, mais pas si vous exécutez votre code à partir du navigateur.

vous pouvez trouver une implémentation complète de NodeJS ici: https://github.com/guyrotem/google-translate-server . il expose une API TTS minimale (requête, langue) et est déployé sur un serveur Heroku gratuit, vous pouvez donc le tester en ligne si vous le souhaitez.

function shiftLeftOrRightThenSumOrXor(num, opArray) {
        return opArray.reduce((acc, opString) => {
                var op1 = opString[1];  //      '+' | '-' ~ SUM | XOR
                var op2 = opString[0];  //      '+' | '^' ~ SLL | SRL
                var xd = opString[2];   //      [0-9a-f]

                var shiftAmount = hexCharAsNumber(xd);
                var mask = (op1 == '+') ? acc >>> shiftAmount : acc << shiftAmount;
                return (op2 == '+') ? (acc + mask & 0xffffffff) : (acc ^ mask);
        }, num);
}

function hexCharAsNumber(xd) {
        return (xd >= 'a') ? xd.charCodeAt(0) - 87 : Number(xd);
}

function transformQuery(query) {
        for (var e = [], f = 0, g = 0; g < query.length; g++) {
          var l = query.charCodeAt(g);
          if (l < 128) {
                e[f++] = l;                                     //      0{l[6-0]}
          } else if (l < 2048) {
                e[f++] = l >> 6 | 0xC0;           //      110{l[10-6]}
                e[f++] = l & 0x3F | 0x80;   //      10{l[5-0]}
          } else if (0xD800 == (l & 0xFC00) && g + 1 < query.length && 0xDC00 == (query.charCodeAt(g + 1) & 0xFC00)) {
                //      that's pretty rare... (avoid ovf?)
                l = (1 << 16) + ((l & 0x03FF) << 10) + (query.charCodeAt(++g) & 0x03FF);
                e[f++] = l >> 18 | 0xF0;          //      111100{l[9-8*]}
                e[f++] = l >> 12 & 0x3F | 0x80;       //      10{l[7*-2]}
                e[f++] = l & 0x3F | 0x80;           //      10{(l+1)[5-0]}
          } else {
                e[f++] = l >> 12 | 0xE0;          //      1110{l[15-12]}
                e[f++] = l >> 6 & 0x3F | 0x80;        //      10{l[11-6]}
                e[f++] = l & 0x3F | 0x80;           //      10{l[5-0]}
          }
        }
        return e;
}

function normalizeHash(encondindRound2) {
        if (encondindRound2 < 0) {
                encondindRound2 = (encondindRound2 & 0x7fffffff) + 0x80000000;
        }
        return encondindRound2 % 1E6;
}

function calcHash(query, windowTkk) {
        //      STEP 1: spread the the query char codes on a byte-array, 1-3 bytes per char
        var bytesArray = transformQuery(query);

        //      STEP 2: starting with TKK index, add the array from last step one-by-one, and do 2 rounds of shift+add/xor
        var d = windowTkk.split('.');
        var tkkIndex = Number(d[0]) || 0;
        var tkkKey = Number(d[1]) || 0;

        var encondingRound1 = bytesArray.reduce((acc, current) => {
                acc += current;
                return shiftLeftOrRightThenSumOrXor(acc, ['+-a', '^+6'])
        }, tkkIndex);

        //      STEP 3: apply 3 rounds of shift+add/xor and XOR with they TKK key
        var encondingRound2 = shiftLeftOrRightThenSumOrXor(encondingRound1, ['+-3', '^+b', '+-f']) ^ tkkKey;

        //      STEP 4: Normalize to 2s complement & format
        var normalizedResult = normalizeHash(encondingRound2);

        return normalizedResult.toString() + "." + (normalizedResult ^ tkkIndex)
}

// usage example:
var tk = calcHash('hola', '409837.2120040981');
console.log('tk=' + tk);
 // OUTPUT: 'tk=70528.480109'
11
Guy Rotem

Tout d'abord, pour éviter le captcha, vous devez définir un agent utilisateur approprié comme:
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv: 46.0) Gecko/20100101 Firefox/46.0"

Pour ne pas être bloqué, vous devez fournir un jeton approprié (paramètre get "tk") pour chaque requête.
. pour récupérer votre jeton simplement en observant des demandes similaires profondes pour traduire la page (avec votre texte dans l'url).
Vous pouvez lire l'heure du jeton en récupérant "tk =" à partir de la sortie de ce code simple avec phantomjs:

"use strict";
var page = require('webpage').create();
var system = require('system');
var args = system.args;
if (args.length != 2) { console.log("usage: "+args[0]+" text");  phantom.exit(1); }
page.onConsoleMessage = function(msg) {     console.log(msg); };
page.onResourceRequested = function(request) {   console.log('Request ' + JSON.stringify(request, undefined, 4)); };
page.open("https://translate.google.it/?hl=it&tab=wT#fr/it/"+args[1],     function(status) {
if (status === "success")    {             phantom.exit(0);           } 
else {      phantom.exit(1);    }
});

donc à la fin vous pouvez obtenir votre discours avec quelque chose comme:
wget -U "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv: 46.0) Gecko/20100101 Firefox/46.0" " http://translate.google.com/translate_tts?ie= UTF-8 & tl = it & tk = 52269.458629 & q = ciao & client = t "-O ciao.mp3
(les jetons sont probablement basés sur le temps, donc ce lien peut ne pas fonctionner demain)

3

Vous pouvez également essayer ce format:

  1. passez le format q = urlencode de votre langue (en JavaScript, vous pouvez utiliser la fonction encodeURI () & PHP a la fonction rawurlencode ())

  2. passer tl = nom abrégé de la langue (supposons que bangla = bn)

Maintenant, essayez ceci:

https://translate.google.com.vn/translate_tts?ie=UTF-8&q=%E0%A6%A2%E0%A6%BE%E0%A6%95%E0%A6%BE+&tl = bn & client = tw-ob

1
Arman Hakim Sagar