Python爬虫有道翻译API(反爬虫)

---------------------------------------------------------------------

  python版本:3.6
  测试日期:2020-03-22
  联系邮箱:betterWL@hotmail.com

---------------------------------------------------------------------

1 分析
——

不同的网站请求数据的方式可能不一样,有静态的、动态的,还有的可能有各种反爬虫机制保护。

所以用到的爬虫方法也不一样,在想着爬取之前我们要先对网站进行分析

有道翻译web版url = http://fanyi.youdao.com/

1.1 动态or静态?

显然数据是动态生成的,因为当我们随便输入一个词来翻译

 右键查看网页源代码时,搜索刚才翻译的“你好”查不到关键字,所以数据肯定时动态生成的。

1.2 过滤有效数据包

打开chrome自带的检查工具(F12)——NetWork,由于动态的数据请求基本都是Ajax来做的,所以我们直接过滤XHR

在翻译页面点一下翻译按钮,可以看到检查工具中多了一个数据包,查看Response选项可以看到返回的是json格式的数据,并且带有翻译后的结果——'hello'

确定这条数据包就是我们要的数据包后,就要分析最重要的属性的了——Headers

1.3分析数据包Headers

一步一步来,我们先确定真正请求数据的url,和请求的方式

url = http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule

请求方式 = POST

与GET请求不同,POST请求的参数不在Query String中,而是在Form Data中。(所以它请求数据前后url并不发生变化,所以可以通过查看点击翻译按钮url并不发生变化判断是POST请求。)

Form Data可以在Headers下最下方看到:

 

进行了多次翻译操作,比对这些参数,可以发现:

      i                 ---------> 要翻译的源字串
ts、salt、sign  ---------> 每次动态变化的

这其实就是有道设置的反爬机制,要破解它就要搞定s、salt、sign这三个参数是我们重点要搞定的,

搞定了他们三个,直接调用requests.post()就可以了

2 反爬虫
——

上面我们说了 ts、salt、sign 这三个参数是动态生成的,既然是动态的,我们就必须找到一种方法来知道他是怎么生成的才能对其进行破解。

2.1 动态参数生成的方法

 这种随机的数据产生的方法通常只有两种:

一是通过请求服务器传回一些莫名其妙的值,这个我们肯定不能去破解,因为我们根本不知道数据生成的逻辑;

二是通过本地的js文件来生成,这种情况我们可以找到生成的方法,也就有机会进行破解。

那么如何判断这些加密的参数到底是从服务器返回的还是本地生成的呢?

其实很简单,还是要看数据包的信息——Initiator,分析请求源。这里有两个js文件,我怀疑是translate这个动作对应的fanyi.min.js是生成参数的js文件。

(Whatever,只有两个js,你挨个试也很简单可以发现哪个对)

点击后面的超链接,打开对应的js文件,复制代码到js格式化的网站,例如:http://edit.qqe2.com/

将格式化好代码复制到一个编辑器(notepad++、sublime都可以)

如果有关于ts、salt、sign的生成方法应该就有相关的代码,进而可知应该会有相关的参数叫ts、salt、sign(命名习惯)

搜索之后,恰好找到具体的生成方法 (●ˇ∀ˇ●)

    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 + "Nw(nmmbP%A-r6U3EUn]Aj")
        }
    };

整理了一下得到:

(1)网站采用的是md5加密
(2)ts = "" + (new Date).getTime()  -----> 单位为毫秒的时间
(3)salt = "" + (new Date).getTime() + parseInt(10 * Math.random(), 10) -----> ts后连接一个[1,10]的整数
4)sign = n.md5("fanyideskweb" + e + i + "@6f#X3=cCuncYssPsuRUE") -----> e为要翻译内容,i=ts,其余为固定字串

得到了动态参数,也就得到了Form Data,也就可以开始编写我们的代码啦, <( ̄︶ ̄)↗[GO!]

3 代码书写

# -*- encoding: utf-8 -*-,
'''
@File    :   youdao.py,
@Time    :   2020/03/21 17:39:40,
@Author  :   bAdblocks ,
@Version :   1.0,
@Contact :   betterWL@hotmail.com,
'''

# here put the import lib
import requests
import time
import random
import hashlib
import json

url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
headers = {
    "Cookie": "OUTFOX_SEARCH_USER_ID=1721894360@59.111.179.141; _ntes_nnid=28c86721ce2c2392d0b4bc1c066195c2,1562810189644; OUTFOX_SEARCH_USER_ID_NCOO=1717529083.05212; P_INFO=qducst_xmt@163.com|1572920094|0|other|00&99|shd&1572744638&mail163#shd&null#10#0#0|&0|mail163|qducst_xmt@163.com; JSESSIONID=aaadMecWfzOYVgeMhs8dx; ___rl__test__cookies=1584780646068",
    "Referer": "http://fanyi.youdao.com/",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36",
}

key = input('请输入需要翻译的文字:') #长度小于5000

# ts,salt,sign 的计算方法见fanyi.min.js 
ts = str(time.time() * 1000)
salt = ts + str(random.randint(1,10))
sign = hashlib.md5(('fanyideskweb' + key + salt + 'Nw(nmmbP%A-r6U3EUn]Aj').encode('utf-8')).hexdigest()

DataForm = {
    "i": key,
    "from": "AUTO",
    "to": "AUTO",
    "smartresult": "dict",
    "client": "fanyideskweb",
    "ts": ts,# 动态获取
    "salt": salt, # 动态获取
    "sign": sign,# 动态获取
    "bv": "70244e0061db49a9ee62d341c5fed82a",# 与jquery的版本有关
    "doctype": "json",
    "version": "2.1",
    "keyfrom": "fanyi.web",
    "action": "FY_BY_CLICKBUTTION"
}

r = requests.post(url, data=DataForm, headers=headers)

result_json = json.loads(r.text)
# print(result_json)

if (result_json['errorCode'] == 40):
    print('抱歉,不认识这个词')
    exit(40)

result = result_json['translateResult'][0][0]['tgt']
print('翻译的结果是:' + result)

原文地址:https://www.cnblogs.com/Irvingcode/p/12544584.html