Python 爬取有道翻译

前情提要

爬取的网站http://fanyi.youdao.com/

遵循业内规则,我们先看一下robots协议http://fanyi.youdao.com/robots.txt
内容是这样的
在这里插入图片描述
OK,可以爬取,那我们就正式开始

分析网页

我们爬虫的第一步自然是先要分析网页,我们先随便输入两个单词
在这里插入图片描述
可以看到,我们在输入内容后,右侧自动出现了翻译结果,这种情况一般是ajax异步加载

这里介绍一下什么是ajax异步加载

AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

摘自https://www.w3school.com.cn/ajax/ajax_intro.asp

打开抓包工具,输入单词来抓取网络请求

输入几个单词,果然得到了结果
在这里插入图片描述
打开请求,发现翻译结果
在这里插入图片描述
看一下请求头,市一个post方法,请求的url是http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
在这里插入图片描述
再来看下请求的表单,发现了一些复杂的参数,其中i,salt,sign,ts,bv看起来是有问题的
在这里插入图片描述
对比其他的请求,发现i:是输入的词,salt,sign,ts不知道是什么,其他的都是固定值

问题来了,salt,sign,ts是哪来的?

js逆向

我们在google浏览器的开发者调试工具(F12)中搜索salt,看下有没有结果
在这里插入图片描述
搜索结果在一个js文件中,我们打开这个文件看一看
在这里插入图片描述
这js代码很明显不是给人看的,但是我们可以按下左下角的**{}将js代码格式化
在这里插入图片描述
格式化的代码如下
在这里插入图片描述
接下来让我们
Ctrl+F**搜索一下我们想要的内容
一个一个往后找,看到了这个
在这里插入图片描述
很明显,salt是由一个名为i的函数生成了

我们按下上一个搜索结果的箭头,看见这样的代码片段
在这里插入图片描述
ts是现在的时间戳的字符串,i是r的后面加上一个随机数乘以10的结果,sign是一个md5结果

注意:js中的时间戳是一个整数,Python中的时间戳是一个浮点数

我们看一下sign的参数:在这里插入图片描述
函数参数e是我们输入的词,而sign的参数是两个字符串加上我们输入的词加上i的值

知道了原理,现在开始写代码

代码实现

md5
先说一下Python中md5的生成
在Python中md5生成需要使用hashlib库的md5
用法:

from hashlib import md5   #导入md5模块
result=md5("String".encode()).hexdigest()   #获取md5结果
print(result)   #输出结果

运行结果

27118326006d3829667a400ad23d5d98

我们用md5函数来生成一个md5对象,其中他的参数是一个二进制数据,在通过hexdigest方法转为md5字符串

时间戳的处理
我们在js中获得的时间戳有13位,而Python中获取的时间戳有17位,所以我们要将Python的时间戳乘以1000再转换成整型

import time
print(int(time.time()*1000))

数据提取
我们来看下返回的json数据在这里插入图片描述
翻译结果是在translateResult中列表第一项的第一项的tgt中,即
[translateResult][0][0][tgt]

接下来开始写代码

代码

我们先导入一些基本的模块,并创建一个Youdao类,定义一下它的初始化方法

import requests
import time
import random
from hashlib import md5


class Youdao():
    def __init__(self):
        self.word = input("输入你要翻译的内容>>>")
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36',
            'Referer': 'http://fanyi.youdao.com/',
            'Cookie': 'OUTFOX_SEARCH_USER_ID=-343678438@10.169.0.83; OUTFOX_SEARCH_USER_ID_NCOO=1469412342.8594604; _ntes_nnid=069631a09195b5119a8e93159593722d,1585795354321; JSESSIONID=aaafrdxrCaUM1hKbBZFhx; ___rl__test__cookies=1588599225405',
        }
        self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

接下来让我们写一个方法来获得参数,返回请求表单

    def get_data(self):
        ts = int(time.time() * 1000)
        salt = str(ts) + str(random.randint(0, 10))
        sign = md5(('fanyideskweb' + self.word + salt + 'Nw(nmmbP%A-r6U3EUn]Aj').encode()).hexdigest()
        return {
            'i': self.word,
            'from': 'AUTO',
            'to': 'AUTO',
            'smartresult': 'dict',
            'client': 'fanyideskweb',
            'salt': salt,
            'sign': sign,
        	'ts': ts,
            'bv': '54005c0ddc47d3a4f8a58b098803c921',
            'doctype': 'json',
            'version': '2.1',
            'keyfrom': 'fanyi.web',
            'action': 'FY_BY_REALTlME',
        }

其中参数的生成方法我已经讲了,可参照上方代码实现部分

最后定义一个请求方法,返回并提取翻译结果

    def translation(self):
        data=self.get_data()
        r=requests.post(self.url,headers=self.headers,data=data).json()
        result=r['translateResult'][0][0]['tgt']
        return result

完整代码如下

import requests
import time
import random
from hashlib import md5


class Youdao():
    def __init__(self):
        self.word = input("输入你要翻译的内容>>>")
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36',
            'Referer': 'http://fanyi.youdao.com/',
            'Cookie': 'OUTFOX_SEARCH_USER_ID=-343678438@10.169.0.83; OUTFOX_SEARCH_USER_ID_NCOO=1469412342.8594604; _ntes_nnid=069631a09195b5119a8e93159593722d,1585795354321; JSESSIONID=aaafrdxrCaUM1hKbBZFhx; ___rl__test__cookies=1588599225405',
        }
        self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

    def get_data(self):
        ts = int(time.time() * 1000)
        salt = str(ts) + str(random.randint(0, 10))
        sign = md5(('fanyideskweb' + self.word + salt + 'Nw(nmmbP%A-r6U3EUn]Aj').encode()).hexdigest()
        return {
            'i': self.word,
            'from': 'AUTO',
            'to': 'AUTO',
            'smartresult': 'dict',
            'client': 'fanyideskweb',
            'salt': salt,
            'sign': sign,
        'ts': ts,
            'bv': '54005c0ddc47d3a4f8a58b098803c921',
            'doctype': 'json',
            'version': '2.1',
            'keyfrom': 'fanyi.web',
            'action': 'FY_BY_REALTlME',
        }
    def translation(self):
        data=self.get_data()
        r=requests.post(self.url,headers=self.headers,data=data).json()
        result=r['translateResult'][0][0]['tgt']
        return result

youdao=Youdao()
result=youdao.translation()
print(result)

原创不易,求支持

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值