JS逆向必会基础案例 | 有道翻译参数破解

动态网页爬虫一般可分为两种:Selenium爬取和接口爬取。两种方式各有优缺点:前者虽然可以很好地处理网页异步加载问题,但面对大型爬虫任务时,效率还是比较低的;后者虽然爬取速度较快,但请求参数很可能是动态变化的,这时就需要利用一些前端的知识,重新构造参数,整个过程通常称为JS逆向

今天,我们就来分享一个JS逆向的基础案例——有道翻译参数破解
在这里插入图片描述

一、分析Post请求参数

爬取网址为有道翻译,利用谷歌浏览器抓包后,找到翻译响应如下:
在这里插入图片描述
注意:响应返回的是post请求,不是以往我们接触的get请求。此时,直接将URL复制到浏览器去访问,是无法获取数据的,如下图所示:
在这里插入图片描述
此时,我们可以通过requests模块中post方法来传入data参数(通常是以字典形式),以此来正常访问页面。

requests.post(url,headers=header,data=from_data #data为需要传入的参数)

那需要传哪些参数呢?我们可以在Headers下的From data中找到,如下图所示:
在这里插入图片描述
在这里插入图片描述

通过比对不同翻译的响应,可知动态参数为i、salt、sign、lts,其中参数i是我们需要翻译的词。因此,我们可以初步构建from_data字典如下:

from_data={
    'i': word,
    'from': 'AUTO',
    'to': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt':salt,
    'sign':sign,
    'lts':lts,
    'bv':'4b1009b506fa4405f21e207abc4459fd',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_CLICKBUTTION',
    }

接下来就是寻找salt、sign、lts是如何构成的,然后传入上述字典即可。

二、分析参数来源

首先,我们打开搜索栏,尝试搜索salt参数(当然其他两个也是可以的),基本步骤如下
在这里插入图片描述
点击进入JS文件后,可按如下方式均可美化代码,便于后续分析代码。
在这里插入图片描述
接下来,按照同样的方法,对参数salt进行搜索,结果共12个。挨个慢慢找哪些是能构成salt参数的,最终结果如下:
在这里插入图片描述
关于navigator.appVersion(new Date).getTime()等这些参数的含义,其实是与javascript相关的语句,通过百度即可了解。不过我们也可以通过console控制台初步了解。点击console控制台,输入console.log(navigator.appVersion)即可得到其结果,如下图所示:

在这里插入图片描述

从上述结果,我们可知道navigator.appVersion与用户代理有关(不知道也没事,反正是个常量),(new Date).getTime()与时间戳非常接近,通过比较时间戳后可知它是当前时间戳乘以1000取整构成的,parseInt(10*Math.random(),10)是生成0-10的随机数。当然,对于sign值还有个e,我们还不了解,这里可以打断点进行分析,如下图所示(断点处不一定非要8376行,在其之后也可以)

在这里插入图片描述
打完断点,点击翻译,即可得到各个参数返回的值。这里,我们整理下各参数值的含义

参数含义
e需要翻译的词
tnavigator.appVersion进行md5加密
r当前时间戳*1000取整
ir值+0-10的随机数
tsr值
bvt值
salti值
sign"fanyideskweb" + e + i + "Tbh5E8=q6U3EXe+&L[4c@" 进行md5加密

三、Python重新构造参数

经过以上分析,我们只要利用Python将上述参数重构即可啦,该部分代码如下:

  • ts值
def get_ts():
    ts=int(time.time()*1000)
    return ts
  • salt值
def get_salt(ts):
    num = int(random.random()*10)
    salt = str(ts) + str(num)
    return salt
  • sign值
def get_sign():
    left = 'fanyideskweb'
    e= 'stop'  #翻译的词
    i = get_salt(get_ts())
    right = 'Tbh5E8=q6U3EXe+&L[4c@'
    str_data = left + e + i + right 
    m=hashlib.md5()
    m.update(str_data.encode('utf-8'))
    sign=m.hexdigest()
    return sign

全部代码

以类进行封装如下(注意,headers要带上cookie)

import requests
import time
import random
import hashlib


class youdao:
    def __init__(self, url, header, word):
        self.url = url
        self.header = header
        self.word = word

    def get_ts(self):
        self.ts = int(time.time()*1000)
        return self.ts

    def get_salt(self, ts):
        self.num = int(random.random()*10)
        self.salt = str(ts) + str(self.num)
        return self.salt

    def get_sign(self, salt):
        left = 'fanyideskweb'
        e = self.word  # 翻译的词,图中的e
        i = salt
        right = 'Tbh5E8=q6U3EXe+&L[4c@'
        str_data = left + e + i + right
        m = hashlib.md5()
        m.update(str_data.encode('utf-8'))
        sign = m.hexdigest()
        return sign

    def get_from_data(self):
        ts = self.get_ts()
        salt = self.get_salt(ts)
        from_data = {
            'i': self.word,
            'from': 'AUTO',
            'to': 'AUTO',
            'smartresult': 'dict',
            'client': 'fanyideskweb',
            'salt': salt,
            'sign': self.get_sign(salt),
            'lts': ts,
            'bv': '4abf2733c66fbf953861095a23a839a8',
            'doctype': 'json',
            'version': '2.1',
            'keyfrom': 'fanyi.web',
            'action': 'FY_BY_CLICKBUTTION',
        }
        return from_data


if __name__ == '__main__':
    url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
    header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36',
              'Referer': 'http://fanyi.youdao.com/',
              'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=920530045.7161942; OUTFOX_SEARCH_USER_ID="1506261127@10.108.160.17"; _ga=GA1.2.1288125049.1599879702; _ntes_nnid=7dc5dc11be36895d173bef7fe1b51cb1,1606305443534; JSESSIONID=aaaAC5o5FTuNsgXAdm7Dx; ___rl__test__cookies=1612686603098'
              }
    word = 'enthusiastic'
    fanyi = youdao(url, header, word)
    r = requests.post(url, headers=header, data=fanyi.get_from_data())
    data = r.json()
    print("输入单词:{},翻译为{}".format(
        data['translateResult'][0][0]['src'], data['translateResult'][0][0]['tgt']))

在这里插入图片描述

以上就是本次分享的全部内容~

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值