用Python製作mini翻譯器的實現示例
1. 例項描述
在平時程式設計的過程中,會經常在網上翻譯一些單詞,本文使用Python製作一款翻譯小工具,不僅可以自己用,還可以嵌入到程式當中。執行程式,效果如下圖所示,在文字框輸入英文或中文,單擊 翻譯
按鈕即可翻譯,並將翻譯內容顯示在下面的文字框中。單擊 儲存
按鈕將輸入內容和翻譯內容儲存到文字檔案中以便日後複習。單擊 清空
按鈕,將清除文字框中的內容。
2. 技術要點
利用 requests
模組獲取 有道詞典web
頁面的 post
資訊,獲取需要的內容,通過 tkinter
模組生成視窗介面,使用檔案讀寫方法將內容儲存到文字檔案中。
2.1 有道詞典這樣的 JS 混淆加密應該怎麼破
嘿嘿嘿,本文需要說說一些爬蟲過程中需要鬥智鬥勇的事情了,這次咱們就來說說關於一些 JS
混淆加密的事。所謂 JS
,就是 JavaScript
,一種前端的指令碼語言,一般情況下每個網站都需要 JS
來做一些資料互動,頁面渲染等一些非同步操作。當然,對於反爬的人來說,JS
的用處還可以用來對一些資料進行加密。
今天咱們就以有道詞典這個線上翻譯的網站為例,看看他們是如何加密請求資料的,以及筆者是如何通過 Python
模擬請求從而獲得關鍵資料的。
點選 此處 開啟有道翻譯的網站:
輸入中文然後點選翻譯按鈕就會翻譯出來英文,比如:
接著我們開啟開發者工具,按下 F12
來抓一下資料,當我們點選翻譯的時候,可以看到有了一個請求:
點進去看可以發現,POST
請求的地址是:
http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
我們再來看一下請求過去攜帶的引數是啥:
可以看到,還是需要挺多引數的,其中的 i
就是我們要翻譯的內容,那簡單啊~想要得到翻譯後的資料,那麼我們直接把請求頭和所需引數的值複製一下,然後用 requests
請求一波不就搞定了?執行一波,返回的是錯誤碼。
我們再點多幾次翻譯按鈕,然後就可以看到有多次請求。
可以發現,每一次的請求中的 salt
、sign
、lts
、bv
引數是會一直變化的。
我們回到NetWork
,我們看到 Initiator
這一欄,可以看到它請求到了 fanyi.min.js:1
這個 js 檔案。
我們就點 fanyi.min.js:1
進去看看,牛的一比,直接看不懂…還好,左下角有一個 {}
,可以點一下,發現有驚喜,直接幫我們把壓縮的 js
程式碼格式化。
牛逼不,行號都給我們顯示出來了,不過到了這裡,依然懵逼,我們還是不知道怎麼拿到 salt
、sign
、lts
、bv
這些引數的值…咋辦?恩,Chrome
瀏覽器的打斷點功能在這個時候就要派上用場。那麼如何使用斷點功能呢,我們看到 Chrome
的右邊是這樣的:
看到這個 XHR/fetch BreakPoints
沒,在這裡我們可以新增 url
,根據請求這個 url
打斷點。而我們要打的斷點就是一開始獲取到的請求 url
:
http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
點選 XHR/fetch BreakPoints
右邊的 +
號,然後把連結複製進去:
這時候再點選翻譯按鈕,突然,你的螢幕一灰,表示好事將近,我們成功打上了斷點,也就是說,現在我們可以在請求之前做一些騷操作。
這時候我們將右邊的 Call Stack
展開,點 t.translate
進去:
這些,就是我們在點選翻譯按鈕之後,會呼叫到 js
裡面的方法,從這裡下手,來尋找引數是被如何加密的,
3. 程式碼實現
用Python製作mini翻譯器的具體步驟如下:
首先安裝 requests
模組。使用 pip
命令安裝,命令如下:
pip install --user -i http://pypi.douban.com/simple --trusted-host pypi.douban.com requests
匯入相關模組,程式碼如下。
import tkinter as tk import requests import time import hashlib import random
定義翻譯函式,程式碼如下。
def get_ts(): """ 獲取時間戳 :return: 時間 """ return str(int(time.time() * 1000)) def get_bv(): """ 獲取app版本 並通過md5加密 :return: 加密後的字串 """ navigator_appVersion = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/78.0.3' \ '904.108 Safari/537.36' m = hashlib.md5() m.update(navigator_appVersion.encode('utf-8')) return m.hexdigest() def get_salt(ts): return str(ts) + str(int(random.random() * 10)) def get_sign(salt): str1 = text1.get() # 定義一個變數,用來接收輸入文字框的值 str_data = 'fanyideskweb' + str1 + salt + ']BjuETDhU)zqSxf-=B#7m' m = hashlib.md5() m.update(str_data.encode('utf-8')) return m.hexdigest() def get_form_data(): str1 = text1.get() # 定義一個變數,用來接收輸入文字框的值 ts = get_ts() salt = get_salt(ts) form_data = { 'i': str1,'from': 'AUTO','to': 'AUTO','smartresult': 'dict','client': 'fanyideskweb','salt': str(salt),'sign': get_sign(salt),'ts': ts,'bv': get_bv(),'doctype': 'json','version': '2.1','keyfrom': 'fanyi.web','action': 'FY_BY_CLICKBUTTION',} return form_data # 定義翻譯函式 def translate(): url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/78.0.3904.108 Safari/537.36','Referer': 'http://fanyi.youdao.com/','Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=173326173.72226533; OUTFOX_SEARCH_USER_ID="[email protected]"; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; JSESSIONID=abcAjF-mxbKFQ_48uyLpx; __guid=204659719.1682486053682624500.1597281254731.5474; monitor_count=2; ___rl__test__cookies=1597285713766' } response = requests.post(url=url,data=get_form_data(),headers=headers) if response.status_code == 200: result = response.json() translate_result = result['translateResult'][0][0]['tgt'] text2.delete(1.0,"end") # 清空輸出文字框 text2.insert('end',translate_result) # 將翻譯結果新增到輸出文字框中
定義寫入文字 txt
的函式,程式碼如下。
# 定義寫入文字txt的函式 def write(): f1 = open('translate.txt','a+') f1.write(text1.get() + ',' + text2.get(0.0,tk.END))
定義清空文字框的函式,程式碼如下。
# 定義清空文字框的函式 def delete(): text1.delete(0,"end") # 從第一行清除到最後一行 text2.delete(1.0,"end")
視窗介面設計,程式碼如下。
if __name__ == '__main__': window = tk.Tk() # 建立window視窗 window.wm_attributes("-topmost",1) # 置頂 window.title("AmoXiang mini翻譯器") # 定義視窗名稱 window.resizable(width=False,height=False) # 決定框體大小是否能夠調整 text1 = tk.Entry(window,width=80,bg='whitesmoke') # 在窗體上新增一個輸入文字框,並設定尺寸和顏色 text2 = tk.Text(window,height=18,bg='lightgrey') # 在窗體上新增一個輸出文字框,並設定尺寸和顏色 text1.grid(row=0,sticky="W",padx=1) text2.grid(row=1) # 新增一個按鈕,用於觸發翻譯功能 t_button = tk.Button(window,text='翻譯',relief=tk.RAISED,width=8,height=1,font='宋體',bg='red',fg='white',command=translate) # 新增一個按鈕,用於觸發清空輸入文字框 button1 = tk.Button(window,text='儲存',command=write) # 新增一個按鈕,用於觸發清空輸出文字框 button2 = tk.Button(window,text='清空',command=delete) # 新增背景圖片 image_file = tk.PhotoImage(file='amo.gif') label = tk.Label(window,image=image_file) # 完成介面佈局,設定各個控制元件的位置 t_button.grid(row=0,column=1,padx=2) button1.grid(row=0,column=2,padx=2) button2.grid(row=0,column=3,padx=2) label.grid(row=1,columnspan=3) tk.mainloop()
到此這篇關於用Python製作mini翻譯器的實現示例的文章就介紹到這了,更多相關Python mini翻譯器內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!