破解有道JS引數,教你用python自制一個翻譯軟體!

qwer1030274531發表於2020-09-18

最近在備考四六級,很多單詞不會,每次都要開啟翻譯軟體就很不方便,就想了一下自己是不是可以用python寫一個翻譯軟體, 查閱了一些資料後, 最後我選擇了有道翻譯的介面,作為本次翻譯網址目標介面,介面選擇了Tkinter作為基礎,最後用python搭建了一個翻譯軟體,本篇文章就是關於這個翻譯軟體的製作教學,喜歡的可以支援一下!

效果圖:
在這裡插入圖片描述

你會收穫百分之八十的js破解,收穫引數的加密方式,收穫Tkinter的基本控制元件操作,收穫python的模組用法,當你看完這篇文章之後!

翻譯小軟體:

    •   設計思路:

    •   js破解:

    •   GUI設計:

    •   程式碼模組:

    •   關於GUI程式碼:

    •   關於Js程式碼部分:

    •   全部程式碼:


設計思路:

js破解
GUI設計
程式
表單資料
軟體雛形
最終效果

js破解:

首先我們開啟有道網頁:
在這裡插入圖片描述
試著輸入簡單 根據NetWork中,我們檢視這個XHR會發現有一些介面網址
類似這樣的一個POST請求方式,

在響應中,我們可以根據json包就能檢視到翻譯後的結果, 這個將會用來我們解析資料中用到, 在看一張圖:

在這裡插入圖片描述
介面沒有變化, 點選標頭, 游標移到最後,有表單資料,英文應該是data forms, 這裡有一些需要提交的資料,在我們向伺服器後臺傳送一個POST請求的時候,是必須要攜帶的資料, 但是這些資料有些是不會變的, 有些是會變化的, 只需要根據二個不同的介面,對比一下就知道了, 在這裡,我對比之後, 發現有4個引數是會變化的, 如下:

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

所以我們就要知道 這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")
        }
    };1234567891011

根據這個函式,我們就可以找到引數是如何構造的,具體怎麼構造,下面細講.


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()1234567891011121314151617181920212223242526272829303132333435363738394041424344454647

異常處理:

    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)12345678

輸出設定:

    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)1234567

清空設定:

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

關於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 = ''
        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': '
            "Referer": "
            'User-Agent': self.ua,
            'X-Requested-With': 'XMLHttpRequest'
        }
        self.__tkinter()123456789101112131415161718192021222324

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()}12345678910111213141516171819202122232425262728

表單資料的構造:

    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'
        }12345678910111213141516171819

傳送請求提交資料:

    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("伺服器繁忙, 請稍後再試!")1234567891011121314151617181920

本篇文章: 關於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_45906219import requestsfrom get_useragent import GetUserAgentCSfrom hashlib import md5import timeimport randomimport tkinter.messageboxfrom tkinter import *class makeTranslate():
    """
    url: 
    破解有道翻譯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 = ''
        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': '
            "Referer": "
            '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()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191

你會收穫百分之八十的js破解,收穫引數的加密方式,收穫Tkinter的基本控制元件操作,收穫python的模組用法,當你看完這篇文章之後!


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30239065/viewspace-2722139/,如需轉載,請註明出處,否則將追究法律責任。

相關文章