python爬虫——有道翻译JS破解

不知道为什么好像网上 js 逆向都属以有道翻译为例子,以前认为 js 逆向很难,但是现在还是要学习。

参考:https://mp.weixin.qq.com/s/a-ORkG5XGSAP_-6GNilBbQ

一、前提

编译IDA:pycharm 社区版
python版本:python3.7.4
用到的库:requests、time、hashlib、random

二、分析

1、找到响应
用浏览器打开有道的在线翻译,按下F12并在框中输入任意中文来观察其网页变化。
可以看到在 http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule 中找到翻译的响应内容
在这里插入图片描述
2、分析请求
这是一个 POST 请求,且表单参数很多
修改要翻译的内容,可以看到每次改变的只有 i、salt、sign、ts、bv,其他的都没有改变

在这里插入图片描述在这里插入图片描述
但其实改变翻译语言还可以看到 from、to、action 的改变,以下是全部解释

'i': 			#输入内容
'from': 		#原始语言
'to': 			#翻译语言
'smartresult': 	#结果类型(固定)
'client': 		#监听器(固定)
'salt': 		#加密
'sign': 		#加密
'ts': 			#时间戳
'bv': 			#浏览器User-Agent
'doctype': 		#json类型
'version': 		#版本
'keyfrom': 		#请求来源(固定)
'action': 		#方式(有实时FY_BY_REALTlME、换语言lan-select、手动点击FY_BY_CLICKBUTTION)

3、js 逆向
一般现在很多都是 js 就可以处理的,所以这些就可以分析 js 来破解参数规则
打开调试器,查找到 fanyi.min.js,ctrl+F 查找 i、salt、sign、ts、bv 其中之一,一般选单词数比较长的,因为不会交叉覆盖好找。
在这里插入图片描述

找到 Ajax 异步提交 data 表单,继续查找,找到他们之间的逻辑
下面就是数据如何处理得到 data 表单的
在这里插入图片描述
ts 就是 r 当前时间的时间戳
bv 就是 t 对浏览器 UA 进行 MD5 加密
salt 就是 i 时间戳加上随机时间
sign 就是字符串加入要翻译的内容、i 进行MD5 加密

ts = str(int(time.time()))
salt = str(int(time.time()) + random.random() * 10 + 10)
sign = 'fanyideskweb' + word + salt + 'n%A-rKaT5fb[Gy?;N5@Tj'
sign = hashlib.md5(sign.encode('utf-8')).hexdigest()
bv = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0'
bv = hashlib.md5(bv.encode('utf-8')).hexdigest()

4、最后POST提交表单即可

三、完整代码

可以直接使用

# !/usr/bin/python
# -*- coding: utf-8 -*- 
# @Time : 2019/12/19 13:05 
# @Author : ljf
# @File : youdao.py

import requests
import time
import hashlib
import random


class youdao_crawl:
    def __init__(self):
        """
        初始化内容
        """
        self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0',
            'Referer': 'http://fanyi.youdao.com/',
            'Cookie': 'YOUDAO_MOBILE_ACCESS_TYPE=1; [email protected]; OUTFOX_SEARCH_USER_ID_NCOO=62105739.76007765; JSESSIONID=aaaNhy9FAvO3l7Ye5HC8w; ___rl__test__cookies=1576732583589'
        }
        self.data = {
            'i': None,
            'from': 'AUTO',
            'to': 'AUTO',
            'smartresult': 'dict',
            'client': 'fanyideskweb',
            'salt': None,
            'sign': None,
            'ts': None,
            'bv': None,
            'doctype': 'json',
            'version': '2.1',
            'keyfrom': 'fanyi.web',
            'action': 'FY_BY_REALTlME'
        }
        
	# def language(self, original, translate):
    #     """
    #     Args:
    #         original:   原始语言
    #         translate:  翻译语言
    #     Returns:        无
    #     """
    #     type = {
    #         'AUTO': 'AUTO',
    #         '中文': 'zh-CHS',
    #         '英语': 'en',
    #         '日语': 'ja',
    #         '韩语': 'ko',
    #         '法语': 'fr',
    #         '德语': 'de',
    #         '俄语': 'ru',
    #         '西班牙语': 'es',
    #         '葡萄牙语': 'pt',
    #         '意大利语': 'it',
    #         '越南语': 'vi',
    #         '印尼语': 'id',
    #         '阿拉伯语': 'ar',
    #     }
    #     self.data['from'] = type[original]
    #     self.data['to'] = type[translate]

    def translate(self, word):
        """
        Args:
            word: 要翻译的内容
        Returns: 无
        """
        ts = str(int(time.time()))
        salt = str(int(time.time()) + random.random() * 10 + 10)
        sign = 'fanyideskweb' + word + salt + 'n%A-rKaT5fb[Gy?;N5@Tj'
        sign = hashlib.md5(sign.encode('utf-8')).hexdigest()
        bv = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0'
        bv = hashlib.md5(bv.encode('utf-8')).hexdigest()
        self.data['i'] = word
        self.data['salt'] = salt
        self.data['sign'] = sign
        self.data['ts'] = ts
        self.data['bv'] = bv

    # def run(self, original, translate, word):
    #     youdao.language(original,translate)
    def run(self, word):
        """
        Args:
            word: 要翻译的内容
        Returns:  翻译后的内容
        """
        youdao.translate(word)
        re = requests.post(self.url, headers=self.headers, data=self.data)
        return re.json()['translateResult'][0][0].get('tgt')


if __name__ == '__main__':
    youdao = youdao_crawl()
    while True:
        content = input("请输入您需要翻译的内容:")
        if content == "q":
            break
        trans = youdao.run(content)
        print(trans)

四、结果

因为是默认的缘故,所以中文都会翻译成英语,其它语言都会翻译成中文
在这里插入图片描述

五、总结

1、疑惑
不知道为什么这些应该都有时效性,每次刷新内置参数都不一样,但是现在还可以,难道是这些参数是固定的只是每次给的都不一样

2、选择语言
选择语言也不麻烦,但是影响代码长度,所以一般默认自动读取就可以了

3、action
换语言:lan-select
实时:FY_BY_REALTlME
手动点击:FY_BY_CLICKBUTTION

4、其它
其他的参数,跟进版本应该没问题

发布了113 篇原创文章 · 获赞 109 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/weixin_42109012/article/details/103615648