JS逆向解析之有道翻译

简单方法 —调用开源api

这个比较简单四行代码就可以搞定,先放代码:

import requests
while True:
    input_data = input('请输入你要翻译的数据:')
    print(requests.get('http://fanyi.youdao.com/translate',params={'doctype':'json',"type":'AUTO','i':input_data}).json()['translateResult'][0][0]['tgt'])

运行结果:
在这里插入图片描述

代码也很好理解,get第一个参数就是调用的api ,第二个字典参数传入了三个数据,doctype为json类型,type为自动,i就是我们要翻译的数据,再调用json()方法就拿到了python能处理的json数据即 :

{'type': 'ZH_CN2EN', 'errorCode': 0, 'elapsedTime': 0, 'translateResult': [[{'src': '历史', 'tgt': 'history'}]]}

我们只需要翻译过后的’tgt’所对应的值‘,接下来就是简单字典取值问题了,
根据健名’translateResult’ 取到值[[{‘src’: ‘你好’, ‘tgt’: ‘hello’}]],再通过列表两次取0索引得到字典{‘src’: ‘历史’, ‘tgt’: ‘history’},最后就是简单的字典通过键’tgt’取值就ok了,一步下来就是:[‘translateResult’][0][0][‘tgt’]

复杂一丢丢的JS解析

打开有道翻译官网,输入翻译的数据,鼠标右键检查,点击network,再点击翻译,
在这里插入图片描述

点第一个数据包,然后点击preview 或者response都能看到翻译结果,证明这个就是我们需要解析的数据包
在这里插入图片描述
在这里插入图片描述
重新回到headers里,往下拉到form表单:
在这里插入图片描述
我们需要分析这些数据的变化及加密方式,
复制一份:

i: 历史
from: AUTO
to: AUTO
smartresult: dict
client: fanyideskweb
salt: 16035204521008
sign: 7a1413f07087cacc38aed4fac47fd403
lts: 1603520452100
bv: 4abf2733c66fbf953861095a23a839a8
doctype: json
version: 2.1
keyfrom: fanyi.web
action: FY_BY_CLICKBUTTION

再如法翻译一个数据,复制form表单和上面的比较:

i: 文化
from: AUTO
to: AUTO
smartresult: dict
client: fanyideskweb
salt: 16035228374568
sign: 62eeb0e657b2d71181d6c87be026bbac
lts: 1603522837456
bv: 4abf2733c66fbf953861095a23a839a8
doctype: json
version: 2.1
keyfrom: fanyi.web
action: FY_BY_CLICKBUTTION

比较得出,动态变化的数据只有四个:

1. i :即我们要翻译的数据
2. salt : 初步推测是以毫秒为单位的时间戳 + 一个随机数字
3. sign :未知的js加密后的数据
4. lts : 以毫秒为单位的时间戳

下面简单介绍一些常用的加密解密方法

常见的加密方法

MD5加密

MD5 是一种单向加密技术(不可逆向解密)。MD5加密算法简单高效且算出的值长度都是固定的, MD5值具有强抗碰撞,对原文件哪怕只修改一个字符,所计算出的MD5值也会发生很大变化。基于这些特性,MD5在数据校验上发挥有很大作用。

在python3中的使用:

import hashlib

a = 'hello!'
b = 'abc'
m1 = hashlib.md5(a.encode()).hexdigest()
m2 = hashlib.md5(b.encode()).hexdigest()
print(m1)  #aed978dd6dffef14c3188d28cf0a272d
print(m2)  #900150983cd24fb0d6963f7d28e17f72

base64加密

base64编码方法简单,但是却并不保险,别人很容易就能获取原始数据,通常是用来对文件进行一种格式化的操作,它是一种双向加密(可以逆向解密).

用法如下:


import base64

a = '123'  
b = '123456789'   

# base64加密
base_a = base64.b64encode(a.encode()).decode()
base_b = base64.b64encode(b.encode()).decode()
print(base_a) # MTIz
print(base_b) # MTIzNDU2Nzg5

# base64解密
aa = base64.b64decode('MTIz'.encode()).decode()
bb = base64.b64decode('MTIzNDU2Nzg5'.encode()).decode()
print(aa) # 123
print(bb) # 123456789

HAMC 加密

hamc 同样是基于hash算法,与上面两个加密不同的是,hamc加密是以一个密钥和一个消息作为输入,生成一个消息摘要输出,主要用于身份验证。

用法:

import hmac,hashlib
h = hmac.new(key='key'.encode(),msg='hello'.encode())
h.update('world!'.encode())
ret = h.hexdigest()
print(ret) # 774bd7473ce15ec74c015338cbf2d421

回归正题,目前大概只有一个sign不确定和那个加盐操作是不是加的随机数,接下来我们就需要具体分析网页了:
1.右上角三个点,点击search
在这里插入图片描述

2.全局搜索框输入sign,点击搜索

在这里插入图片描述
3.进入一个带有sign的文件之后,点击pretty-print或者左下角的{},格式化输出显示方便观察。
在这里插入图片描述

4.鼠标点击文件内部页面,ctrl+f 又有搜索框 输入sign
在这里插入图片描述

5.点第二个红框右边的往下找,找到sign定义相关的代码
在这里插入图片描述

6.可以在下方,或者直接断点在sign值,然后呢启动程序
7.直接点击翻译,那么程序就会跑起来,就会执行生成sign值的js文件,然后会卡在断点处
在这里插入图片描述
可以看到加盐操作确实是随机生成的一个数,sign是经过md5加密,由四个字符串拼接而成:“fanyideskweb” + e + i + “]BjuETDhU)zqSxf-=B#7m”

1.鼠标放在t的加密参数上面,可以得知我们的user-gent要和bv值 相 对应 因为bv的数据 是根据 user-gent 进行md5加密得来的
2.bv值由md5根据uset-agent参数加密得到
在这里插入图片描述

3.确实是以毫秒为单位的时间戳
4.证实salt最后一位数字是random随机得到的
5.sign值也是通过md5加密得到的,需要知道md5加密所用到的参数是什么
是四个部分用来做加密的参数

1 . “fanyideskweb”
2 .e : 要被翻译的数据
3 .salt : 毫秒为单位的时间戳 + 随机数字一个
4 . “]BjuETDhU)zqSxf-=B#7m”

至此,所有的参数解密完毕,可以开始编写代码了,具体参考代码如下:

import requests  # 发送网络请求
import time  # 导入时间戳
import random  # 需要产生随机数进行加盐
import hashlib  # 需要用到md5加密
import jsonpath  # 解析json格式数据

# 函数的封装>>> 调用函数就能够得到翻译过后的数据
def youdao():
    while True:
        # 确认目标的url
        url_ = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

        # 设置请求头  用户代理, referer跳转, cookie
        headers_ = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
            "Referer": "http://fanyi.youdao.com/",
            "Cookie": "OUTFOX_SEARCH_USER_ID=1652516314@10.108.160.100; OUTFOX_SEARCH_USER_ID_NCOO=120640644.01846737; JSESSIONID=aaaJTKtlJxbeXfLP5cwvx; ___rl__test__cookies=1603527703671"
        }

        # 设置form表单的参数
        input_data = input('请输入你要翻译的数据:')  # 要被翻译的数据

        time_ = str(int(time.time() * 1000))  # 以毫秒为单位的时间戳

        time_salt = time_ + str(random.randint(0, 9))  # salt加盐操作 以毫秒为单位的时间戳 + 随机数字

        # 拼接字符串进行md5加密,生成sign值
        a = "fanyideskweb" + input_data + time_salt + "]BjuETDhU)zqSxf-=B#7m"
        sign = hashlib.md5(a.encode()).hexdigest()

        # 发送post请求要携带的表单数据
        form_data = {
            "i": input_data,  # 要被翻译的数据
            "from": "AUTO",
            "to": "AUTO",
            "smartresult": "dict",
            "client": "fanyideskweb",
            "salt": time_salt,  # 以毫秒为单位的时间戳 + 随机数字
            "sign": sign,  # 未知的js加密后的数据
            "lts": time_,  # 以毫秒为单位的时间戳
            "bv": "4abf2733c66fbf953861095a23a839a8",
            "doctype": "json",
            "version": "2.1",
            "keyfrom": "fanyi.web",
            "action": "FY_BY_REALTlME",
        }
        try:
            # 利用requests发送post请求,得到响应对象
            response_ =requests.post(url_,headers=headers_,data=form_data)

            # 得到响应对象,数据为json格式数据
            py_data = response_.json()  # 直接转成python数据类型

            # 利用jsonpath解析,得到翻译数据
            res_ = jsonpath.jsonpath(py_data,'$..tgt')[0]

            print(res_)
        except:
            print('请出入正确格式的数据:')
            continue
        time.sleep(1)  # 降低请求频率 避免被封禁IP

if __name__ == '__main__':
    youdao()

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰履踏青云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值