目录
- 1. 实例描述
- 2. 技术要点
- 2.1 有道词典这样的 JS 混淆加密应该怎么破
- 3. 代码实现
1. 实例描述
在平时编程的过程中,会经常在网上翻译一些单词,本文使用Python制作一款翻译小工具,不仅可以自己用,还可以嵌入到程序当中。运行程序,效果如下图所示,在文本框输入英文或中文,单击 翻译 按钮即可翻译,并将翻译内容显示在下面的文本框中。单击 保存 按钮将输入内容和翻译内容保存到文本文件中以便日后复习。单击 清空 按钮,将清除文本框中的内容。
2. 技术要点
利用 requests 模块获取 有道词典web 页面的 post 信息,获取需要的内容,通过 tkinter 模块生成窗口界面,使用文件读写方法将内容保存到文本文件中。
2.1 有道词典这样的 JS 混淆加密应该怎么破
嘿嘿嘿,本文需要说说一些爬虫过程中需要斗智斗勇的事情了,这次咱们就来说说关于一些 JS 混淆加密的事。所谓 JS ,就是 JavaScript,一种前端的脚本语言,一般情况下每个网站都需要 JS 来做一些数据交互,页面渲染等一些异步操作。当然,对于反爬的人来说,JS 的用处还可以用来对一些数据进行加密。
今天咱们就以有道词典这个在线翻译的网站为例,看看他们是如何加密请求数据的,以及笔者是如何通过 Python 模拟请求从而获得关键数据的。
点击 此处 打开有道翻译的网站:
输入中文然后点击翻译按钮就会翻译出来英文,比如:
接着我们打开开发者工具,按下 F12 来抓一下数据,当我们点击翻译的时候,可以看到有了一个请求:
点进去看可以发现,POST 请求的地址是:
;smartresult=rule 1
我们再来看一下请求过去携带的参数是啥:
可以看到,还是需要挺多参数的,其中的 i 就是我们要翻译的内容,那简单啊~想要得到翻译后的数据,那么我们直接把请求头和所需参数的值复制一下,然后用 requests 请求一波不就搞定了?运行一波,返回的是错误码。
我们再点多几次翻译按钮,然后就可以看到有多次请求。
可以发现,每一次的请求中的 salt、sign、lts、bv 参数是会一直变化的。
我们回到 NetWork ,我们看到 Initiator 这一栏,可以看到它请求到了 这个 js 文件。
我们就点 进去看看,牛的一比,直接看不懂…还好,左下角有一个 {} ,可以点一下,发现有惊喜,直接帮我们把压缩的 js 代码格式化。
牛逼不,行号都给我们显示出来了,不过到了这里,依然懵逼,我们还是不知道怎么拿到 salt、sign、lts、bv 这些参数的值…咋办?恩,Chrome 浏览器的打断点功能在这个时候就要派上用场。那么如何使用断点功能呢,我们看到 Chrome 的右边是这样的:
看到这个 XHR/fetch BreakPoints 没,在这里我们可以添加 url ,根据请求这个 url 打断点。而我们要打的断点就是一开始获取到的请求 url :
;smartresult=rule 1
点击 XHR/fetch BreakPoints 右边的 + 号,然后把链接复制进去:
这时候再点击翻译按钮,突然,你的屏幕一灰,表示好事将近,我们成功打上了断点,也就是说,现在我们可以在请求之前做一些骚操作。
这时候我们将右边的 Call Stack 展开,点 t.translate 进去:
这些,就是我们在点击翻译按钮之后,会调用到 js 里面的方法,从这里下手,来寻找参数是被如何加密的,
3. 代码实现
用Python制作mini翻译器的具体步骤如下:
- 首先安装 requests 模块。使用 pip 命令安装,命令如下:pip install --user -i --trusted-host requests 1
- 导入相关模块,代码如下。import tkinter as tk import requests import time import hashlib import random 12345
- 定义翻译函数,代码如下。def get_ts(): """ 获取时间戳 :return: 时间 """ return str(in() * 1000)) def get_bv(): """ 获取app版本 并通过md5加密 :return: 加密后的字符串 """ navigator_appVersion = 'Mozilla (windows NT 10.0; WOW64) AppleWebKi (KHTML, like Gecko) Chrome; \ '904.108 Safari; m = () m.update('utf-8')) return m.hexdigest() def get_salt(ts): return str(ts) + str(in() * 10)) def get_sign(salt): str1 = () # 定义一个变量,用来接收输入文本框的值 str_data = 'fanyideskweb' + str1 + salt + ']BjuETDhU)zqSxf-=B#7m' m = () m.update('utf-8')) return m.hexdigest() def get_form_data(): str1 = () # 定义一个变量,用来接收输入文本框的值 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': ';, 'action': 'FY_BY_CLICKBUTTION', } return form_data # 定义翻译函数 def translate(): url = ";smartresult=rule" headers = { 'User-Agent': 'Mozilla (Windows NT 10.0; WOW64) AppleWebKi (KHTML, like Gecko) Chrome Safari;, 'Referer': ';, 'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=173326173.72226533; OUTFOX_SEARCH_USER_ID="-1202396372@10.108.160.18"; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; JSESSIONID=abcAjF-mxbKFQ_48uyLpx; __guid=204659719.1682486053682624500.31.5474; monitor_count=2; ___rl__test__cookies=66' } response = reque(url=url, data=get_form_data(), headers=headers) if re == 200: result = re() translate_result = result['translateResult'][0][0]['tgt'] , "end") # 清空输出文本框 ('end', translate_result) # 将翻译结果添加到输出文本框中 1234567891011128192021222324252627282930337383940414243444546474849505575859606162636465666768
- 定义写入文本 txt 的函数,代码如下。# 定义写入文本txt的函数 def write(): f1 = open(';, 'a+') (() + ',' + , )) 1234
- 定义清空文本框的函数,代码如下。# 定义清空文本框的函数 def delete(): (0, "end") # 从第一行清除到最后一行 , "end") 1234
- 窗口界面设计,代码如下。if __name__ == '__main__': window = () # 创建window窗口 window.wm_attributes("-topmost", 1) # 置顶 window.title("AmoXiang mini翻译器") # 定义窗口名称 window.resizable(width=False, height=False) # 决定框体大小是否能够调整 text1 = (window, width=80, bg='whitesmoke') # 在窗体上添加一个输入文本框,并设置尺寸和颜色 text2 = (window, height=18, bg='lightgrey') # 在窗体上添加一个输出文本框,并设置尺寸和颜色 (row=0, sticky="W", padx=1) (row=1) # 添加一个按钮,用于触发翻译功能 t_button = (window, text='翻译', relief=, width=8, height=1, font='宋体', bg='red', fg='white', command=translate) # 添加一个按钮,用于触发清空输入文本框 button1 = (window, text='保存', font='宋体', relief=, width=8, height=1, command=write) # 添加一个按钮,用于触发清空输出文本框 button2 = (window, text='清空', font='宋体', relief=, width=8, height=1, command=delete) # 添加背景图片 image_file = (file='amo.gif') label = (window, image=image_file) # 完成界面布局,设置各个控件的位置 (row=0, column=1, padx=2) bu(row=0, column=2, padx=2) bu(row=0, column=3, padx=2) label.grid(row=1, column=1, columnspan=3) () 123456789101112819202122232425
至此今天的案例就到此结束了,笔者在这里声明,笔者写文章只是为了学习交流,以及让更多学习Python基础的读者少走一些弯路,节省时间。
最后,小编想说:我是一名python开发工程师,
整理了一套最新的python系统学习教程,
想要这些资料的可以关注私信小编“01”即可(免费分享哦)希望能对你有所帮助