unity免费使用谷歌翻译(使用tk值,防止数量限制的错误)

如果直接使用

string url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl="
                    + sourceLang + "&tl=" + targetLang + "&dt=t&q=" + UnityWebRequest.EscapeURL(sourceText);

这种url去谷歌翻译那里获取翻译的话,会有限制,因为没有token值,所以很容易会给谷歌那边屏蔽ip,无法再翻译。后面找了一下资料,发现有些是使用了tk值的方式来访问谷歌翻译,经过验证,很频繁(每隔0.2s翻译一条)翻译,翻译是上万条也没出现给限制的情况。这种方法的难点就在tk值的获取,其实tk值在使用GET方式访问https://translate.google.cn的时候就可以获取到,但是这个tk值还需要做一些处理,才能重新使用。下面说下怎么获取。

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using YIMEngine;
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;

public class Translate
{
    protected struct ExternalKey
    {
        ///


        /// Total hours
        ///

        public long Time { get; }

        ///


        /// Token value
        ///

        public long Value { get; }

        /// Unix-formatted total hours
        /// Token value
        public ExternalKey(long time, long value)
        {
            Time = time;
            Value = value;
        }
    }

    protected static int UnixTotalHours
    {
        get
        {
            DateTime unixTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return (int)DateTime.UtcNow.Subtract(unixTime).TotalHours;
        }
    }
    // We have use googles own api built into google Translator.
    public static IEnumerator Process(string targetLang, string sourceText, System.Action result, int times)
    {
        yield return Process("auto", targetLang, sourceText, result, times);
    }

    // Exactly the same as above but allow the user to change from Auto, for when google get's all Jerk Butt-y
    public static IEnumerator Process(string sourceLang, string targetLang, string sourceText, System.Action result,
        int times)
    {
        //第一步,先使用GET方式访问谷歌翻译,拿到html的tk值
        string urlte = "https://translate.google.cn";
        UnityWebRequest request1 = new UnityWebRequest(urlte, "GET");

        request1 .SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
        request1 .downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
        request1 .useHttpContinue = false;//应对某些机型的errorCallback with error=java.io.EOFException
        yield return request1.SendWebRequest();
        if (request1.isNetworkError || request1.isHttpError)
        {
            Debug.LogError("获取服务器列表失败 = " + request1.error);
            result.Invoke("", times);
            yield break;
        }

        long tkk = 0;

        try
        {
            //这个就是返回的初始tk值
            var tkkText = request1.downloadHandler.text.GetTextBetween(@"tkk:'", "',");

            if (tkkText == null)
            {
                result.Invoke("", times);
            }

            var splitted = tkkText.Split('.');
            if (splitted.Length != 2 || !long.TryParse(splitted[1], out tkk))
            {
                result.Invoke("", times);
            }

        }
        catch (ArgumentException)
        {
            result.Invoke("", times);
        }

        var currentExternalKey = new ExternalKey(UnixTotalHours, tkk);
        long time = DecrypthAlgorythm(sourceText, currentExternalKey);

        string tk = time.ToString() + '.' + (time ^ currentExternalKey.Time);

        string address = "https://translate.google.cn/translate_a/single";
        string url =$"{ address}" + "?" + 
                    $"sl={sourceLang}&" +
                    $"tl={targetLang}&" +
                    $"hl={sourceLang}&" +
                    $"q={UnityWebRequest.EscapeURL(sourceText)}&" +
                    $"tk={tk}&" +
                    "client=t&" +
                    "dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&" +
                    "ie=UTF-8&" +
                    "oe=UTF-8&" +
                    "otf=1&" +
                    "ssel=0&" +
                    "tsel=0&" +
                    "kc=7";
        //Debug.Log("地址=" + url);
        //string url = string.Format("https://translate.google.cn/translate_a/single?client=t&sl={0}&tl={1}&hl={0}&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at&ie=UTF-8&oe=UTF-8&ssel=6&tsel=3&kc=0&tk=" + tk + "&q={2}", sourceLang, targetLang, UnityWebRequest.EscapeURL(sourceText));
        /*        string url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl="
                    + sourceLang + "&tl=" + targetLang + "&dt=t&q=" + UnityWebRequest.EscapeURL(sourceText);*/
        UnityWebRequest request = new UnityWebRequest(url, "GET");
        //request.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
        request.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
        request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
        request.useHttpContinue = false;//应对某些机型的errorCallback with error=java.io.EOFException
        yield return request.SendWebRequest();
        if (request.isNetworkError || request.isHttpError)
        {
            Debug.LogError("获取服务器列表失败 = " + request.error);
            result.Invoke("", times);
            yield break;
        }
        
        JsonData jsonData = JsonMapper.ToObject(request.downloadHandler.text);
        string translatedText = jsonData[0][0][0].ToString();
        //Debug.Log("返回的text=" + request.downloadHandler.text);
        Debug.Log("解析后=" + translatedText);
        result.Invoke(translatedText, times);
    }

    private static long DecrypthAlgorythm(string source, ExternalKey CurrentExternalKey)
    {
        List code = new List();

        for (int g = 0; g < source.Length; g++)
        {
            int l = source[g];
            if (l < 128)
            {
                code.Add(l);
            }
            else
            {
                if (l < 2048)
                {
                    code.Add(l >> 6 | 192);
                }
                else
                {
                    if (55296 == (l & 64512) && g + 1 < source.Length && 56320 == (source[g + 1] & 64512))
                    {
                        l = 65536 + ((l & 1023) << 10) + (source[++g] & 1023);
                        code.Add(l >> 18 | 240);
                        code.Add(l >> 12 & 63 | 128);
                    }
                    else
                    {
                        code.Add(l >> 12 | 224);
                    }
                    code.Add(l >> 6 & 63 | 128);
                }
                code.Add(l & 63 | 128);
            }
        }

        long time = CurrentExternalKey.Time;

        foreach (long i in code)
        {
            time += i;
            Xr(ref time, "+-a^+6");
        }

        Xr(ref time, "+-3^+b+-f");

        time ^= CurrentExternalKey.Value;

        if (time < 0)
            time = (time & int.MaxValue) + 2147483648;

        time %= (long)1e6;

        return time;
    }

    private static void Xr(ref long a, string b)
    {
        for (int c = 0; c < b.Length - 2; c += 3)
        {
            long d = b[c + 2];

            d = 'a' <= d ? d - 87 : (long)char.GetNumericValue((char)d);
            d = '+' == b[c + 1] ? (long)((ulong)a >> (int)d) : a << (int)d;
            a = '+' == b[c] ? a + d & 4294967295 : a ^ d;
        }
    }
}

下面是string的拓展方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

static class StringExtension
{
    internal static string GetTextBetween(this string src, string from, string to, int startIndex = 0)
    {
        if (src == null)
            throw new ArgumentNullException(nameof(src));
        if (from == null)
            throw new ArgumentNullException(nameof(from));
        if (to == null)
            throw new ArgumentNullException(nameof(to));
        if (startIndex < 0 || startIndex > src.Length - 1)
            throw new ArgumentOutOfRangeException(nameof(to));

        int index = src.IndexOf(from, startIndex, StringComparison.Ordinal);
        if (index == -1)
            return null;

        int index2 = src.IndexOf(to, index, StringComparison.Ordinal);
        if (index2 == -1)
            return null;

        var result = src.Substring(index + from.Length, index2 - index - from.Length);
        return result;
    }


    internal static string ToCamelCase(this string src)
    {
        string[] words = src.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

        return string.Concat(words.Select(word
            => char.ToUpper(word[0]) + word.Substring(1).ToLower()));
    }

}
 

 

 

你可能感兴趣的:(unity免费使用谷歌翻译(使用tk值,防止数量限制的错误))