爬虫入门经典(二十) | 破解JS加密之有道翻译

不温卜火 54 0 0

  大家好,我是不温卜火,是一名计算机学院大数据专业大三的学生,昵称来源于成语—不温不火,本意是希望自己性情温和。作为一名互联网行业的小白,博主写博客一方面是为了记录自己的学习过程,另一方面是总结自己所犯的错误希望能够帮助到很多和自己一样处于起步阶段的萌新。但由于水平有限,博客中难免会有一些错误出现,有纰漏之处恳请各位大佬不吝赐教!暂时只在csdn这一个平台进行更新,博客主页:https://buwenbuhuo.blog.csdn.net/1

PS:由于现在越来越多的人未经本人同意直接爬取博主本人文章,博主在此特别声明:未经本人允许,禁止转载!!!

目录


2


推荐

23
  ♥各位如果想要交流的话,可以加下QQ交流群:974178910,里面有各种你想要的学习资料。♥

  ♥欢迎大家关注公众号【不温卜火】,关注公众号即可以提前阅读又可以获取各种干货哦,同时公众号每满1024及1024倍数则会抽奖赠送机械键盘一份+IT书籍1份哟~♥
24

一、小小课堂

3
本文是应粉丝要求写的,本来可能要等到我有空闲时间再写,但是由于博主最近看了关于JS破解的相关知识。就想着先找个实战demo进行测试,这就是此篇博文产出的大题过程。

之前博主做了通过百度翻译的接口制作一个简易的翻译软件。当时由于没有想太多,只是对其汉译英与英译汉进行了简单的测试就发了出来。后来经过粉丝的测试,告知了我此程序在翻译句子的时候会报错。如下图:
4

博主在破解了有道翻译之后,再次测试,发现翻译句子可以完美运行,如下图:
5
嗯!这也算是间接的增加了翻译的功能了哈哈!

二、加密与解密

我们在爬取数据时,有的数据是通过加密解密得到的。这时,有人会问道什么是加密?那么又是如何解密的呢?

加密与解密,通俗的来讲就是:

  • 加密:把明文变成密文
  • 解密:把密文变成明文

市面上常见的加密方式有三种:

  • 1、js加密
  • 2、css加密
  • 3、base64加密

25
本篇博文讲解的是js加密的破解

本次选用的案例为有道翻译:http://fanyi.youdao.com/
6
下面咱们要做的就是模拟有道翻译进行单词的翻译。

三、分析

26

3.1 分析尝试(初次)

  • 1.翻译一句话
    7
    1. 查看URL

这个时候我们就可以拿到我们请求的URL
8
URL为:

http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule 
    1. 查找参数
      9
      先把此部分复制出来
"""
i: 你好
from: AUTO
to: AUTO
smartresult: dict
client: fanyideskweb
salt: 16032741765278
sign: b25367e1be33d7529a099d200c8f7dd3
lts: 1603274176527
bv: 4abf2733c66fbf953861095a23a839a8
doctype: json
version: 2.1
keyfrom: fanyi.web
action: FY_BY_CLICKBUTTION
""" 

我们将其转换成字典(dict),代码如下

from pprint import pprint

data = """i: 你好
from: AUTO
to: AUTO
smartresult: dict
client: fanyideskweb
salt: 16032741765278
sign: b25367e1be33d7529a099d200c8f7dd3
lts: 1603274176527
bv: 4abf2733c66fbf953861095a23a839a8
doctype: json
version: 2.1
keyfrom: fanyi.web
action: FY_BY_CLICKBUTTION"""

pprint({i.split(": ")[0]:i.split(": ")[1] for i in data.splitlines()}) 

10
把此部分复制出来如下:

{'action': 'FY_BY_CLICKBUTTION',
 'bv': '4abf2733c66fbf953861095a23a839a8',
 'client': 'fanyideskweb',
 'doctype': 'json',
 'from': 'AUTO',
 'i': '你好',
 'keyfrom': 'fanyi.web',
 'lts': '1603274176527',
 'salt': '16032741765278',
 'sign': 'b25367e1be33d7529a099d200c8f7dd3',
 'smartresult': 'dict',
 'to': 'AUTO',
 'version': '2.1'} 
    1. 添加请求头

我们先来看下,有道翻页此网页的请求头
11
我们可以看到有多种请求,其实一般我们爬取网页内容,并不需要全部添加,除非需要。一般我们添加User-Agent即可。
在此,博主由于已经提前测试过了。因此就给出所需要的请求头部分

headers = {
    'X-Requested-With': 'XMLHttpRequest',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
    'Origin': 'http://fanyi.youdao.com',
    'Referer': 'http://fanyi.youdao.com/',
    'Cookie': 'OUTFOX_SEARCH_USER_ID=-1808168645@10.108.160.208; JSESSIONID=aaaRyVJv8oEwg7dPaWrux; OUTFOX_SEARCH_USER_ID_NCOO=704285648.1294403; ___rl__test__cookies=1602406917270'
} 
    1. 测试代码

🆗,到这我们就可以进行初步测试了。代码如下:

import requests

url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
headers = {
    'X-Requested-With': 'XMLHttpRequest',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
    'Origin': 'http://fanyi.youdao.com',
    'Referer': 'http://fanyi.youdao.com/',
    'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=1393050056.867326; OUTFOX_SEARCH_USER_ID="1960068844@10.108.160.18"; _ga=GA1.2.1058335445.1601859339; P_INFO=18240707138|1602644960|1|youdaonote|00&99|null&null&null#hen&410100#10#0|&0|null|18240707138; _gid=GA1.2.1420409534.1603269583; JSESSIONID=aaaimJ33Iywd1fQBRukvx; ___rl__test__cookies=1603274176525'
}
data = {'action': 'FY_BY_CLICKBUTTION',
        'bv': '9caf244986fe6d1de38207408302e500',
        'client': 'fanyideskweb',
        'doctype': 'json',
        'from': 'AUTO',
        'i': '你好',
        'keyfrom': 'fanyi.web',
        'lts': '1603274176527',
        'salt': '16032741765278',
        'sign': 'b25367e1be33d7529a099d200c8f7dd3',
        'smartresult': 'dict',
        'to': 'AUTO',
        'version': '2.1'
}
response = requests.post(url=url,headers=headers,data=data)
print(response.content.decode("utf-8")) 

12
我们这时发现,当修改翻译内容的时候,得不到想要的结果。其实做为一个合格的爬虫开发者,应该有敏感性。

二、JS破解

27
我们此时可以重新看一下所获取的参数:
13

2.1 验证时间戳

此时我们可以进行验证。

百度搜索时间戳在线转换工具即可。链接:https://tool.lu/timestamp/

    1. lts
      14
    1. salt

我们先来对比下lts和salt

 'lts': '1603274176527',
        'salt': '16032741765278', 

通过对比我们发现,只是多了最后一个数字,那么salt到底是什么呢?我们现在并不知道,不过我们可以通过查找确定其位置,然后判定其到底是什么。

2.2 JS的破解方式

1. 普通JS的破解方式

15
这种方法不经常使用, 因为一旦出现多个相同的JS就很麻烦,

2. 通用JS破解方式

    1. 先通过Srearch查找translate_o 16
    1. 格式化JS 然后继续搜索translate_o 17
    1. 查找salt:
      18
    1. 断点调试js,查看变量值,再次确认。

由于之前已经验证过,所以在此直接给出怎样查找
19
断点位置,博主已经提前给出
20
在此,我们先把此部分copy出来

 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")
        }
    }; 

经过分析,确认参数:

ts是当前时间戳

bv是使用md5加密navigator.appVersion,只要浏览器不变,其实可以是固定的
21

salt是时间戳拼接0-9的随机整数字符串

sgin是md5加密的

这里的e通过断点调试确认e就是翻译的内容

3. python模拟MD5加密

    1. 模拟its和salt
import time
import random

its = str(round(time.time(),3)).replace(".","")
salt = its+str(random.randint(0,9))

print(its,salt) 

22

    1. MD5加密模拟

MD5算法一般用来加密,不可逆。
此部分内容随机输入,最终都是32位的加密字符串

import hashlib

content = "我不温卜火"
md5 = hashlib.md5()
md5.update(content.encode("utf-8"))
ret = md5.hexdigest()
print(ret,len(ret)) 

23

    1. 程序中的对比
sign: n.md5("fanyideskweb" + e + i + "]BjuETDhU)zqSxf-=B#7m")

# 此部分修改为
sign = do_md5("fanyideskweb" + params + salt + "]BjuETDhU)zqSxf-=B#7m") 

三、完整代码

33

# encoding: utf-8
'''
  @author 李华鑫
  @create 2020-10-10 17:07
  Mycsdn:https://buwenbuhuo.blog.csdn.net/
  @contact: 459804692@qq.com
  @software: Pycharm
  @file: 有道翻译.py
  @Version:1.0

'''
import requests
import time
import random
import hashlib
from pprint import pprint

def main():
    """主程序"""
    url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
    headers = {
        'X-Requested-With': 'XMLHttpRequest',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
        'Origin': 'http://fanyi.youdao.com',
        'Referer': 'http://fanyi.youdao.com/',
        'Cookie': 'OUTFOX_SEARCH_USER_ID=-1808168645@10.108.160.208; JSESSIONID=aaaRyVJv8oEwg7dPaWrux; OUTFOX_SEARCH_USER_ID_NCOO=704285648.1294403; ___rl__test__cookies=1602406917270'
    }
    while True:
        params = input("请输入单词:")
        data = get_data(params)
        response = requests.post(url=url,headers=headers,params=params,data=data)
        print(response.json()["translateResult"][0][0]["tgt"])

def do_md5(content):
    """md5方法"""
    md5 = hashlib.md5()
    md5.update(content.encode("utf-8"))
    return md5.hexdigest()

def get_data(params):
    """获取参数"""
    lts = str(round(time.time(), 3)).replace(".", "")
    salt = lts + str(random.randint(0, 9))
    sign = do_md5("fanyideskweb" + params + salt + "]BjuETDhU)zqSxf-=B#7m")
    data = {
        'action': 'FY_BY_CLICKBUTTION',
        'bv': '9caf244986fe6d1de38207408302e500',
        'client': 'fanyideskweb',
        'doctype': 'json',
        'from': 'AUTO',
        'i': params,
        'keyfrom': 'fanyi.web',
        'lts': lts,
        'salt': salt,
        'sign': sign,
        'smartresult': 'dict',
        'to': 'AUTO',
        'version': '2.1'
    }
    return data

if __name__ == '__main__':
        main() 

四、运行测试

24
25
美好的日子总是短暂的,虽然还想继续与大家畅谈,但是本篇博文到此已经结束了,如果还嫌不够过瘾,不用担心,我们下篇见!


12

  好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
  如果我的博客对你有帮助、如果你喜欢我的博客内容,请“点赞” “评论”“收藏”一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
  码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦!

21
22

本文转自 https://buwenbuhuo.blog.csdn.net/article/details/109190900,如有侵权,请联系删除。

预览图
收藏
评论区