最近在备考四六级,很多单词不会,每次都要打开翻译软件就很不方便,就想了一下自己是不是可以用python写一个翻译软件, 查阅了一些资料后, 最后我选择了有道翻译的接口,作为本次翻译网址目标接口,界面选择了Tkinter作为基础,最后用python搭建了一个翻译软件,本篇文章就是关于这个翻译软件的制作教学,喜欢的可以支持一下!
效果图:
你会收获百分之八十的js破解,收获参数的加密方式,收获Tkinter的基本控件操作,收获python的模块用法,当你看完这篇文章之后!
读后有收获,点赞,关注,加收藏,共勉!
点我,点我,点我呀!博主其他文章
设计思路:
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