小言_互联网的博客

破解有道JS参数,教你用python自制一个翻译软件!

360人阅读  评论(0)

最近在备考四六级,很多单词不会,每次都要打开翻译软件就很不方便,就想了一下自己是不是可以用python写一个翻译软件, 查阅了一些资料后, 最后我选择了有道翻译的接口,作为本次翻译网址目标接口,界面选择了Tkinter作为基础,最后用python搭建了一个翻译软件,本篇文章就是关于这个翻译软件的制作教学,喜欢的可以支持一下!

效果图:

你会收获百分之八十的js破解,收获参数的加密方式,收获Tkinter的基本控件操作,收获python的模块用法,当你看完这篇文章之后!

读后有收获,点赞,关注,加收藏,共勉!
点我,点我,点我呀!博主其他文章


设计思路:

js破解
GUI设计
程序
表单数据
软件雏形
最终效果

js破解:

首先我们打开有道网页:

试着输入简单 根据NetWork中,我们查看这个XHR会发现有一些接口网址
http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule 类似这样的一个POST请求方式,

在响应中,我们可以根据json包就能查看到翻译后的结果, 这个将会用来我们解析数据中用到, 在看一张图:


界面没有变化, 点击标头, 光标移到最后,有表单数据,英文应该是data forms, 这里有一些需要提交的数据,在我们向服务器后台发送一个POST请求的时候,是必须要携带的数据, 但是这些数据有些是不会变的, 有些是会变化的, 只需要根据二个不同的接口,对比一下就知道了, 在这里,我对比之后, 发现有4个参数是会变化的, 如下:

 "salt": "15975022964104",
 "sign": "7b7db70e0d1a786a43a6905c0daec508",
  "lts": "1597502296410",
  "bv": "9ef72dd6d1b2c04a72be6b706029503a",

所以我们就要知道 这4个参数 是如何生成的, 以及如何加密的, 这里就需要利用到浏览器的DEBUG功能, 比如第一个参数 salt 找一找这个是怎么来的, 步骤如下:


点击连接 就可以在上面看到 如箭头 最后点击方框内符号

跳转之后如下: 这里需要细心一点, 观察是否salt 这些参数是否出现了 出现了 就停下来仔细看


然后把光标放到这个函数 ,会立即高亮,显示一个链接, 点击这个链接,就可以直接跳转到这个函数,

函数如下:

var r = function(e) {
   
        var t = n.md5(navigator.appVersion)
          , r = "" + (new Date).getTime()
          , i = r + parseInt(10 * Math.random(), 10);
        return {
   
            ts: r,
            bv: t,
            salt: i,
            sign: n.md5("fanyideskweb" + e + i + "]BjuETDhU)zqSxf-=B#7m")
        }
    };

根据这个函数,我们就可以找到参数是如何构造的,具体怎么构造,下面细讲.


GUI设计:

GUI还是用简单的Tkinter进行设计, 简单粗暴, 关于输入的异常,做出了空值的判断,如下:

然后就是基本的控件设置: 这个在代码模块中讲


你会收获百分之八十的js破解,收获参数的加密方式,收获Tkinter的基本控件操作,收获python的模块用法,当你看完这篇文章之后!

读后有收获,点赞,关注,加收藏,共勉!
点我,点我,点我呀!博主其他文章


代码模块:

关于GUI代码:

用于生成一个GUI界面, 添加一些基本控件的操作显示。

基本代码:

    def __tkinter(self):
        """using the tkinter get a  GUI model """
        self.window = Tk()  # 生成主题空间
        self.window.title("自制有道翻译小工具")
        # 设置基本参数
        width = 800
        height = 400
        # 获取屏幕尺寸以计算布局参数,让窗口位于屏幕中央
        screenwidth = self.window.winfo_screenwidth()
        screenheight = self.window.winfo_screenheight()
        align_str = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)

        self.window.geometry(align_str)  # 设置窗口大小
        # 设置窗口是否可变长、宽,True:可变,False:不可变
        self.window.resizable(width=True, height=True)
        # 设置一些基本控件
        self.name = Label(self.window, text="Try to translate !", bg="wheat", fg="black", font=("宋体", 50))
        self.name.place(relx=0.15, rely=0.15)
        # 下滑线
        self.hr = Label(self.window, text=self.GetHr(width=width))
        self.hr.place(rely=0.37)
        # Help Tip
        help_s = "(程序支持中文和英语的转换 - 请在左边输入待翻译语句 - 按下按钮后 -  右边则会显示翻译结果)"
        self.Tip = Label(self.window, text=help_s, font=('宋体', 12), fg='Tan')
        self.Tip.place(rely=0.05)
        # InputTextStream
        self.InputTextStream = Text(self.window, bg="Pink", font=('宋体', 15))
        self.InputTextStream.place(relwidth=0.4, rely=0.4, relheight=0.5)
        # OutPutTextStream
        self.OutPutTextStream = Text(self.window, bg="Tan", font=('宋体', 15))
        self.OutPutTextStream.place(relx=0.6, relwidth=0.4, rely=0.4, relheight=0.5)
        # Translate Button
        self.Translate = Button(self.window, text="翻译",
                                command=lambda: self.start(InputStream=self.InputTextStream.get(1.0, END)))
        self.Translate.place(relx=0.42, rely=0.55)
        # Exit Button
        self.exit = Button(self.window, text="退出", command=self.window.destroy)
        self.exit.place(relx=0.52, rely=0.55)
        # clean the InputText
        self.clean_input = Button(self.window, text="清左", command=lambda: self.clean_all(self.InputTextStream))
        self.clean_input.place(relx=0.42, rely=0.7)
        # clean the OutputText
        self.clean_ouput = Button(self.window, text="清右", command=lambda: self.clean_all(self.OutPutTextStream))
        self.clean_ouput.place(relx=0.52, rely=0.7)

        self.window.mainloop()


异常处理:

    def get_messageBox(self, Tips):
        """
        params : Tips from other function to using the messageBox
        function Used to handle warnings for exceptions
        return:  the boolean function  if using click the yes  button return True  else return False
        """
        tkinter.messagebox.showinfo("提示", Tips)

输出设置:

    def print_OutPut(self, OutPut_i):
        """print the translate on the OutPutText"""
        self.OutPutTextStream.delete(1.0, END)
        # Line_max = 20
        # lens = len(OutPut_i) // Line_max
        self.OutPutTextStream.insert(END, OutPut_i)

清空设置:

    def clean_all(self, one_text):
        one_text.delete(1.0, END)
        self.get_messageBox("删除成功!")

关于Js代码部分:

用于参数的解密, 表单数据的提交, 关于json的解析。以及tkinter与模块之间的联系:

基础设置:

    def __init__(self):
        """
        as params:  ua is browser user-agent but i like using  my function in other package
                    Cookies of headers maybe abate because time limit
                    others of headers you should copy the network
        """

        self.ua = GetUserAgentCS().get_user()
        self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
        self.headers = {
   
            'Accept': 'application/json, text/javascript, */*; q=0.01',
            'Accept-Encoding': "gzip, deflate",
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
            'Connection': 'keep-alive',
            'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8",
            'Cookie': 'OUTFOX_SEARCH_USER_ID=1989505748@10.108.160.19; OUTFOX_SEARCH_USER_ID_NCOO=1338955488.841036; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; JSESSIONID=abcwjDskhc0wMbAIKxDrx; ___rl__test__cookies=1599399356674',
            'Host': "fanyi.youdao.com",
            'Origin': 'http://fanyi.youdao.com',
            "Referer": "http://fanyi.youdao.com/?keyfrom=fanyi-new.logo",
            'User-Agent': self.ua,
            'X-Requested-With': 'XMLHttpRequest'
        }
        self.__tkinter()

js的获取:

    def getJSParams(self, Input_i):
        """
          var r = function(e) {
        var t = n.md5(navigator.appVersion)
          , r = "" + (new Date).getTime()
          , i = r + parseInt(10 * Math.random(), 10);
        return {
            ts: r,
            bv: t,
            salt: i,
            sign: n.md5("fanyideskweb" + e + i + "]BjuETDhU)zqSxf-=B#7m")
        }
    };
        这是后台关于 一些参数 的加密函数
        用python去实现这段js代码就可以了
        """
        t = md5()
        t.update(self.ua.encode("utf8"))  # 构造bv参数

        r = int(time.time() * 1000)  # 构造时间参数r

        i = str(r) + str(random.randint(0, 9))  # 构造salt参数r

        sign_t = md5()
        sign_t.update(("fanyideskweb" + Input_i + i + ']BjuETDhU)zqSxf-=B#7m').encode("utf8"))  # 构造sign参数

        return {
   'ts': str(r), 'bv': t.hexdigest(), 'salt': i, "sign": sign_t.hexdigest()}

表单数据的构造:

    def __params(self, item, Input_i):
        """这些参数一定要自己复制的"""

        self.params = {
   
            'i': Input_i,
            'from': 'AUTO',
            'to': 'AUTO',
            'smartresult': 'dict',
            'client': 'fanyideskweb',
            'salt': item.get('salt'),
            'sign': item.get('sign'),
            'lts': item.get('ts'),
            'bv': item.get('bv'),
            'doctype': 'json',
            'version': '2.1',
            'keyfrom': 'fanyi.web',
            'action': 'FY_BY_REALTlME'
        }

发送请求提交数据:

    def start(self, InputStream):
        """
        Params : InputStream  from the Text
        """
        if len(InputStream) == 1:
            #  判断输入为空
            self.get_messageBox("你好像还没有输入要翻译的话噢!")
        else:
            Js_item = self.getJSParams(InputStream.strip())
            self.__params(Js_item, InputStream.strip())
            # 更改翻译内容
            r = requests.post(self.url, headers=self.headers, params=self.params)
            time.sleep(0.7)
            if r.status_code == 200:
                OutPUt_i = r.json().get('translateResult')[0][0].get('tgt')
                print(OutPUt_i)
                self.print_OutPut(OutPUt_i)
            else:
                self.get_messageBox("服务器繁忙, 请稍后再试!")

本篇文章: 关于js解密思路源于: https://blog.csdn.net/llllllkkkkkooooo/article/details/108030148
鸣谢!

你会收获百分之八十的js破解,收获参数的加密方式,收获Tkinter的基本控件操作,收获python的模块用法,当你看完这篇文章之后!

读后有收获,点赞,关注,加收藏,共勉!
点我,点我,点我呀!博主其他文章

全部代码:

# -*- coding :  utf-8 -*-
# @Time      :  2020/9/2  16:32
# @author    :  沙漏在下雨
# @Software  :  PyCharm
# @CSDN      :  https://me.csdn.net/qq_45906219
import requests
from get_useragent import GetUserAgentCS
from hashlib import md5
import time
import random
import tkinter.messagebox
from tkinter import *


class makeTranslate():
    """
    url: http://fanyi.youdao.com/
    破解有道翻译js代码
    制作一个自动翻译器 附带GUI界面
    最后将其打包一个小的桌面程序
    """

    def __init__(self):
        """
        as params:  ua is browser user-agent but i like using  my function in other package
                    Cookies of headers maybe abate because time limit
                    others of headers you should copy the network
        """

        self.ua = GetUserAgentCS().get_user()
        self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
        self.headers = {
   
            'Accept': 'application/json, text/javascript, */*; q=0.01',
            'Accept-Encoding': "gzip, deflate",
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
            'Connection': 'keep-alive',
            'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8",
            'Cookie': 'OUTFOX_SEARCH_USER_ID=1989505748@10.108.160.19; OUTFOX_SEARCH_USER_ID_NCOO=1338955488.841036; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; JSESSIONID=abcwjDskhc0wMbAIKxDrx; ___rl__test__cookies=1599399356674',
            'Host': "fanyi.youdao.com",
            'Origin': 'http://fanyi.youdao.com',
            "Referer": "http://fanyi.youdao.com/?keyfrom=fanyi-new.logo",
            'User-Agent': self.ua,
            'X-Requested-With': 'XMLHttpRequest'
        }
        self.__tkinter()

    @staticmethod
    def GetHr(width):
        """
        return a  long size line enough
        """
        Max_Line = width
        return Max_Line * "-"

    def __tkinter(self):
        """using the tkinter get a  GUI model """
        self.window = Tk()  # 生成主题空间
        self.window.title("自制有道翻译小工具")
        # 设置基本参数
        width = 800
        height = 400
        # 获取屏幕尺寸以计算布局参数,让窗口位于屏幕中央
        screenwidth = self.window.winfo_screenwidth()
        screenheight = self.window.winfo_screenheight()
        align_str = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)

        self.window.geometry(align_str)  # 设置窗口大小
        # 设置窗口是否可变长、宽,True:可变,False:不可变
        self.window.resizable(width=True, height=True)
        # 设置一些基本控件
        self.name = Label(self.window, text="Try to translate !", bg="wheat", fg="black", font=("宋体", 50))
        self.name.place(relx=0.15, rely=0.15)
        # 下滑线
        self.hr = Label(self.window, text=self.GetHr(width=width))
        self.hr.place(rely=0.37)
        # Help Tip
        help_s = "(程序支持中文和英语的转换 - 请在左边输入待翻译语句 - 按下按钮后 -  右边则会显示翻译结果)"
        self.Tip = Label(self.window, text=help_s, font=('宋体', 12), fg='Tan')
        self.Tip.place(rely=0.05)
        # InputTextStream
        self.InputTextStream = Text(self.window, bg="Pink", font=('宋体', 15))
        self.InputTextStream.place(relwidth=0.4, rely=0.4, relheight=0.5)
        # OutPutTextStream
        self.OutPutTextStream = Text(self.window, bg="Tan", font=('宋体', 15))
        self.OutPutTextStream.place(relx=0.6, relwidth=0.4, rely=0.4, relheight=0.5)
        # Translate Button
        self.Translate = Button(self.window, text="翻译",
                                command=lambda: self.start(InputStream=self.InputTextStream.get(1.0, END)))
        self.Translate.place(relx=0.42, rely=0.55)
        # Exit Button
        self.exit = Button(self.window, text="退出", command=self.window.destroy)
        self.exit.place(relx=0.52, rely=0.55)
        # clean the InputText
        self.clean_input = Button(self.window, text="清左", command=lambda: self.clean_all(self.InputTextStream))
        self.clean_input.place(relx=0.42, rely=0.7)
        # clean the OutputText
        self.clean_ouput = Button(self.window, text="清右", command=lambda: self.clean_all(self.OutPutTextStream))
        self.clean_ouput.place(relx=0.52, rely=0.7)

        self.window.mainloop()

    def clean_all(self, one_text):
        one_text.delete(1.0, END)
        self.get_messageBox("删除成功!")

    def __params(self, item, Input_i):
        """这些参数一定要自己复制的"""

        self.params = {
   
            'i': Input_i,
            'from': 'AUTO',
            'to': 'AUTO',
            'smartresult': 'dict',
            'client': 'fanyideskweb',
            'salt': item.get('salt'),
            'sign': item.get('sign'),
            'lts': item.get('ts'),
            'bv': item.get('bv'),
            'doctype': 'json',
            'version': '2.1',
            'keyfrom': 'fanyi.web',
            'action': 'FY_BY_REALTlME'
        }

    def getJSParams(self, Input_i):
        """
          var r = function(e) {
        var t = n.md5(navigator.appVersion)
          , r = "" + (new Date).getTime()
          , i = r + parseInt(10 * Math.random(), 10);
        return {
            ts: r,
            bv: t,
            salt: i,
            sign: n.md5("fanyideskweb" + e + i + "]BjuETDhU)zqSxf-=B#7m")
        }
    };
        这是后台关于 一些参数 的加密函数
        用python去实现这段js代码就可以了
        """
        t = md5()
        t.update(self.ua.encode("utf8"))  # 构造bv参数

        r = int(time.time() * 1000)  # 构造时间参数r

        i = str(r) + str(random.randint(0, 9))  # 构造salt参数r

        sign_t = md5()
        sign_t.update(("fanyideskweb" + Input_i + i + ']BjuETDhU)zqSxf-=B#7m').encode("utf8"))  # 构造sign参数

        return {
   'ts': str(r), 'bv': t.hexdigest(), 'salt': i, "sign": sign_t.hexdigest()}

    def get_messageBox(self, Tips):
        """
        params : Tips from other function to using the messageBox
        function Used to handle warnings for exceptions
        return:  the boolean function  if using click the yes  button return True  else return False
        """
        tkinter.messagebox.showinfo("提示", Tips)

    def print_OutPut(self, OutPut_i):
        """print the translate on the OutPutText"""
        self.OutPutTextStream.delete(1.0, END)
        # Line_max = 20
        # lens = len(OutPut_i) // Line_max
        self.OutPutTextStream.insert(END, OutPut_i)

    def start(self, InputStream):
        """
        Params : InputStream  from the Text
        """
        if len(InputStream) == 1:
            #  判断输入为空
            self.get_messageBox("你好像还没有输入要翻译的话噢!")
        else:
            Js_item = self.getJSParams(InputStream.strip())
            self.__params(Js_item, InputStream.strip())
            # 更改翻译内容
            r = requests.post(self.url, headers=self.headers, params=self.params)
            time.sleep(0.7)
            if r.status_code == 200:
                OutPUt_i = r.json().get('translateResult')[0][0].get('tgt')
                print(OutPUt_i)
                self.print_OutPut(OutPUt_i)
            else:
                self.get_messageBox("服务器繁忙, 请稍后再试!")


if __name__ == '__main__':
    makeTranslate()

你会收获百分之八十的js破解,收获参数的加密方式,收获Tkinter的基本控件操作,收获python的模块用法,当你看完这篇文章之后!

读后有收获,点赞,关注,加收藏,共勉!
点我,点我,点我呀!博主其他文章


转载:https://blog.csdn.net/qq_45906219/article/details/108455438
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场