web-dev-qa-db-ja.com

Google Translate TTS APIがブロックされました

Googleはcaptchaを実装して、人々がTTS翻訳APIにアクセスできないようにしました https://translate.google.com/translate_tts?ie=UTF-8&q=test&tl=zh-TW 。モバイルアプリケーションで使用していました。現在、何も返されていません。キャプチャを回避するにはどうすればよいですか?

21
ginsengtang

修飾子 '&client = tw-ob'をクエリの最後に追加します。 https://translate.google.com/translate_tts?ie=UTF-8&q=test&tl=zh-TW&client=tw-ob

この回答は一貫して機能しなくなりました。これを過度に悪用すると、IPアドレスが一時的にGoogleによってブロックされます。

23
ginsengtang

3つの主要な問題があります。

  1. クエリ文字列に「client」を含める必要があります(client = tは機能しているようです)。
  2. (AJAXを使用して取得しようとする場合)HTTPリクエストのリファラーはhttps://translate.google.com/でなければなりません
  3. 「tk」フィールドはすべてのクエリで変更され、一致するハッシュを入力する必要があります。 .google.com:(コンソールで「window.TKK」と入力)。この応答の最後にあるハッシュ関数(calcHash)を参照してください。

要約する:

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.

=> TKKにアクセスするには、Google翻訳ウェブサイトを開き、開発者ツールのコンソールで「TKK」と入力します(例:「410353.1336369826」)。

TKK値は1時間ごとに変化するため、古いTKKはある時点でブロックされる可能性があり、それを更新する必要がある場合があります(ただし、古いキーは長い間機能するようです)。

tKKを定期的に更新したい場合、かなり簡単に自動化できますが、ブラウザからコードを実行している場合は自動化できません。

nodeJSの完全な実装は、ここで見つけることができます: https://github.com/guyrotem/google-translate-server 。最小限のTTS API(クエリ、言語)を公開し、無料のHerokuサーバーにデプロイされるため、必要に応じてオンラインでテストできます。

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

まず、キャプチャを回避するには、次のような適切なユーザーエージェントを設定する必要があります。
"Mozilla/5.0(X11; Ubuntu; Linux x86_64; rv:46.0​​)Gecko/20100101 Firefox/46.0"

次に、ブロックされないようにするには、単一のリクエストごとに適切なトークン( "tk" getパラメーター)を提供する必要があります。
ウェブ上では、多くのリバースエンジニアリングの後にトークンを計算しようとするさまざまな種類のスクリプトを見つけることができます。 (URLにテキストを含む)ページを翻訳するための同様の深いリクエストで観察するだけでトークンを取得します。
この単純なコードの出力からphantomjsを使用して、「tk =」をgreppingすることで、トークンの時間を読み取ることができます。

"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);    }
});

そのため、最終的には次のようなスピーチを得ることができます。
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
(トークンはおそらく時間ベースであるため、このリンクは明日機能しない可能性があります)

この形式を試すこともできます:

  1. あなたの言語のq = urlencode形式を渡します(JavaScriptでは、encodeURI()関数を使用できます&PHPにはrawurlencode()関数があります)

  2. tl =言語の短縮名を渡す(bangla = bnと仮定)

今これを試してください:

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