爬虫之有道翻译

有道翻译采用js加密的方式,阻碍我们使用代码进行翻译。所以本文手把手教你破解有道js加密方式

1. 首先不考虑js加密情况

1.1 第一步打开有道翻译首页,简单输入一个单词,在检查->Network中分析请求响应

1.2 查看请求的url地址和请求方式,请求体



1.3 代码实现,加上请求头,请求体

from urllib import request,parse

def youdao():

    #请求地址
    url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
    # 请求体
    data = {
        "i": "girl",
        "from":"AUTO",
        "to": "AUTO",
        "smartresult": "dict",
        "client": "fanyideskweb",
        "salt": "1526736521130",  ### 盐:很长的随机串,防止用字典反推
        "sign": "a18e780b545d559a3a1f9647b91c6ed0",  ## 签名:js加密
        "doctype": "json",
        "version": "2.1",
        "keyfrom": "fanyi.web",
        "action": "FY_BY_REALTIME",
        "typoResult": "false"
    }

    #数据编码
    data = parse.urlencode(data).encode()

    headers = {
            "Accept": "application/json,text/javascript,*/*;q = 0.01",
            # "Accept-Encoding": "gzip,deflate",      #### 啥意思。。查。。有它就会错误
            "Accept-Language": "zh-CN,zh;q = 0.8",
            "Connection": "keep-alive",
            "Content-Length": "200",
            "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
            "Cookie":"YOUDAO_EAD_UUID=c7c1d171-272e-443f-9d07-d9f8c779342e; _ntes_nnid=f691c54e993915b7e783b9985d6cc6aa,1490533835544; __guid=204659719.1198573978453254000.1502548625976.454; OUTFOX_SEARCH_USER_ID_NCOO=937151153.4321815; [email protected]|1523271382|0|other|00&99|bej&1523189875&hzhr#bej&null#10#0#0|157818&0|hzhr|[email protected]; [email protected]; _ga=GA1.2.667209885.1524559124; JSESSIONID=aaaTQDWkaB_7QbzNHL4nw; monitor_count=1; fanyi-ad-id=44547; fanyi-ad-closed=1; ___rl__test__cookies=1526736521106",
            "Host":"fanyi.youdao.com",
            "Origin":"http://fanyi.youdao.com",
            "Referer":"http://fanyi.youdao.com/",
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
    }

    req = request.Request(url=url,data=data,headers=headers)

    rsp = request.urlopen(req)

    html = rsp.read().decode()
    print(html)

if __name__ == '__main__':
    youdao()

可以看到正确的输出结果


1.4 但是当你使用同样的代码翻译其它单词时,例如'boy'等就会出现各种各样的错误



2. 破解有道的js加密

2.1 分析发送请求时提交的Form Data,数据中的salt(盐)和sign(签名)是常见的js加密方式,salt是一个很长的随机串,是防止程序员使用字典反推({明文:密文}--{密文:明文})的形式破解加密方式(增加了原字符串的数量,使破解难以完成)。sign也是一种js加密方式,它的原理后边会详细阐述。


2.2 js加密的方式是在浏览器(客户端)进行的,所以我们要分析有道翻译使用的js代码,找到其中对应的salt和sign。

js源码也是右键->检查->Network查看,如图


2.3 将代码复制出来,由于代码格式比较乱,所以使用http://tool.oschina.net/codeformat/js点击打开链接





2.4 在代码中,使用salt和sign关键字查找它们出现在代码中的位置


并且加密方式,为


2.5 可以在浏览器控制台(console)执行js代码,看看这些加密公式实现了哪些功能,因为后续需要我们用python实现,比如(new Date).getTime()是计算的当前时间的时间戳(从1970年到现在的毫秒数)(省略了一些小数点位数),所以对应的python打码为time.time()它返回的是从1970年到现在的秒数,所以还需*10,并且取整。所以在python中具体计算salt的加密函数为


def get_salt():
    '''

    :return:
    '''
    import time,random

    salt = int(time.time()*1000)+random.randint(0,10)

    return salt

2.6 sign的加密方式使用了md5加密算法,即消息摘要算法第五版,提供消息的完整性保护,由js代码可知md5()的参数是一个由四个字符串组成的字符串,第一个和第二个都是常字符串,第三个是所谓的salt,第四个是输入要翻译的单词


所以在python中实现sign的加密方式的方法如下

def get_md5(v):

    import hashlib
    # Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护
    md5 = hashlib.md5()   #md5对象,md5不能反解,但是加密是固定的,就是关系是一一对应,所以有缺陷,可以被对撞出来

    ## update需要一个bytes格式参数
    md5.update(v.encode('utf-8'))  #要对哪个字符串进行加密,就放这里
    value = md5.hexdigest()  #拿到加密字符串

    return value

def get_sign(key,salt):

    sign = 'fanyideskweb' + key + str(salt) + 'ebSeFb%=XZ%T[KZ)c(sy!'

    sign = get_md5(sign)

    return sign
2.7 这样破解了salt和sign的加密方式,再加上1.1实现的翻译代码,我们就可以愉快的用代码实现有道翻译了,整合前边代码,
def get_salt():
    '''

    :return:
    '''
    import time,random

    salt = int(time.time()*1000)+random.randint(0,10)

    return salt

def get_md5(v):

    import hashlib
    # Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护
    md5 = hashlib.md5()   #md5对象,md5不能反解,但是加密是固定的,就是关系是一一对应,所以有缺陷,可以被对撞出来

    ## update需要一个bytes格式参数
    md5.update(v.encode('utf-8'))  #要对哪个字符串进行加密,就放这里
    value = md5.hexdigest()  #拿到加密字符串

    return value

def get_sign(key,salt):

    sign = 'fanyideskweb' + key + str(salt) + 'ebSeFb%=XZ%T[KZ)c(sy!'

    sign = get_md5(sign)

    return sign

from urllib import request,parse

def youdao(key):

    #请求地址
    url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

    salt = get_salt()

    # 请求体
    data = {
        "i": key,
        "from":"AUTO",
        "to": "AUTO",
        "smartresult": "dict",
        "client": "fanyideskweb",
        "salt": str(salt),  ### 盐:很长的随机串,防止用字典反推
        "sign": get_sign(key,salt),  ## 签名:js加密
        "doctype": "json",
        "version": "2.1",
        "keyfrom": "fanyi.web",
        "action": "FY_BY_REALTIME",
        "typoResult": "false"
    }

    #数据编码
    data = parse.urlencode(data).encode()

    headers = {
            "Accept": "application/json,text/javascript,*/*;q = 0.01",
            # "Accept-Encoding": "gzip,deflate",      #### 啥意思。。查。。有它就会错误
            "Accept-Language": "zh-CN,zh;q = 0.8",
            "Connection": "keep-alive",
            "Content-Length": len(data),
            "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
            "Cookie":"YOUDAO_EAD_UUID=c7c1d171-272e-443f-9d07-d9f8c779342e; _ntes_nnid=f691c54e993915b7e783b9985d6cc6aa,1490533835544; __guid=204659719.1198573978453254000.1502548625976.454; OUTFOX_SEARCH_USER_ID_NCOO=937151153.4321815; [email protected]|1523271382|0|other|00&99|bej&1523189875&hzhr#bej&null#10#0#0|157818&0|hzhr|[email protected]; [email protected]; _ga=GA1.2.667209885.1524559124; JSESSIONID=aaaTQDWkaB_7QbzNHL4nw; monitor_count=1; fanyi-ad-id=44547; fanyi-ad-closed=1; ___rl__test__cookies=1526736521106",
            "Host":"fanyi.youdao.com",
            "Origin":"http://fanyi.youdao.com",
            "Referer":"http://fanyi.youdao.com/",
            "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
    }

    req = request.Request(url=url,data=data,headers=headers)

    rsp = request.urlopen(req)

    html = rsp.read().decode()
    print(html)

if __name__ == '__main__':
    youdao("boy")


猜你喜欢

转载自blog.csdn.net/qq_36653505/article/details/80378869