Python爬虫:百度翻译接口获取翻译结果

分析百度翻译接口,使用python获取翻译结果

目标:获取百度翻译结果

工具:chrome/firefox浏览器、pychram、python3.7

模块:requests、re、execjs

开始分析:

首先在翻译页面左边输入字符串,会自动检测语言并将翻译结果显示在右边,这个过程页面并没有刷新,所以分析应该是ajax请求了接口获取的结果,直接筛选XHR,发现最后一个请求就是翻译结果接口;
图1
既然接口找到了,接下来就是分析看传递了哪些参数,一共八个参数:

from: zh
to: en
query: 你好
transtype: realtime
simple_means_flag: 3
sign: 232427.485594
token: c156c49e36c6a5d8625e1919bf915c6e
domain:common

参数from、to:多次尝试后发现分别是原文语言和翻译语言的简称;
参数query:翻译原文;
参数transtype:应该是翻译类型,多次尝试发现有两种结果realtime和translang;
参数simple_means_flag:固定值;
参数sign:应该是js生成的;
参数token:应该也是一段js生成的字符串;
参数domain:固定值。

参数初步分析完成,固定值不用改,现在只需要知道sign和token是怎样生成的就行。

通过搜索sign,发现这个index_4029c2d.js文件中sign调用函数y(n)传入了一个n
图2
打个断点调试看看,发现这个n其实就是需要翻译的原文
图3
继续往下调试,发现函数y其实就是这个函数e,通过函数e、函数n加密后得到sign,ok,接下来将代码复制出来测试,经过js调试发现这段代码报错
图4
浏览器调试看了下,i 就是window全局对象gtk , u=gtk
图5
再次搜索gtk,找到gtk对比前面浏览器调试u的值,发现果然一模一样,这个值就是翻译页面加载出来的,直接请求这个页面正则匹配就能获得gtk,那么也就解决了获取gtk问题
图6
将js代码变量u直接赋值为这个值放到js调试,看是否和浏览器得到的结果一样。
图7
通过对比,发现一模一样,至此sign参数搞定,利用这段js代码就可以生成sign
图片8
接下来分析token参数,刚刚搜索sign其实已经知道(不清楚的回到上面搜索sign那里看看),token参数是从window全局对象common中获取的,通过搜索发现,token其实和gtk是在同一个页面,那么一样使用正则匹配就能拿到
图9
通过再次对比,确认sign和token参数获取方式都没错,参数分析完成,开始写代码
图10
逻辑梳理:
请求翻译页 => 获取gtk、token => 生成sign => 请求翻译接口 => 解析得到翻译结果

代码:

import requests
import re
import execjs
from requests.packages.urllib3.exceptions import InsecureRequestWarning

# 关闭ssl验证错误提醒
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


class FanYi:
    def __init__(self, keyword):
        self.keyword = keyword
        self.url = ['https://fanyi.baidu.com/?aldtype=16047',
                    'https://fanyi.baidu.com/v2transapi?']
        self.session = requests.session()
        self.headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                          '(KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
            'referer': 'https://fanyi.baidu.com/?aldtype=16047',
            'origin': 'https://fanyi.baidu.com',
        }

    def key_parameter(self):
        headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                          '(KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36'
        }
        response = self.session.get(self.url[0], headers=headers, verify=False).content.decode()
        # 获取页面中的token/gtk
        token = re.findall("token: '(.*?)',", response)[0]
        gtk = re.findall("window.gtk = '(.*?)';", response)[0]
        # 读取js
        with open('baidu.js', 'r') as f:
            js = f.read()
        # 生成js对象
        exec_obj = execjs.compile(js)
        # 调用js中的e函数并传入参数生成sign
        sign = exec_obj.call("e", self.keyword, gtk)
        return token, sign

    def form_data(self, token, sign):
        data = {
            'from': 'zh',
            'to': 'en',
            'query': self.keyword,
            'transtype': 'realtime',
            'simple_means_flag': 3,
            'sign': sign,
            'token': token,
            'domain': 'common'
        }
        return data

    def run(self):
        # 调用两次key_parameter函数以保证token为最新的,否则请求不到数据
        self.key_parameter()
        token, sign = self.key_parameter()
        form_data = self.form_data(token, sign)
        data = self.session.post(self.url[1], headers=self.headers, data=form_data, verify=False).json()
        result = data['trans_result']['data'][0]['dst']
        print('翻译结果:', result)


if __name__ == '__main__':
    word = input('请输入原文: ')
    fy = FanYi(word)
    fy.run()

大功告成,运行后可以成功获取到翻译结果。

遇到的问题:之前运行后一直不行,发现是token问题,获取两次token,使用第二次的token就行了,可能是百度的反爬?另外貌似还是有个问题,会偶尔请求失败,需要重新运行,目前原因不明,百度反爬措施还是挺多的。。。

总结:总之完成了翻译结果获取,其中的重点就是sign参数的获取,需要层层分析,打断点调试、抠js代码(js我还是比较菜。。。)分析完后这篇文章也最终干货满满。另外js代码就不放出来了,直接按我上面的方法就能找到js代码直接复制到一个文件中就行,把代码中的 u(这个值其实固定死也行,貌似浏览器上面也是固定的)赋值一下就行。

PS:本文只提供一些思路,随着时间的推移,网站会维护,以上代码不会一直都有效,需要重新分析。

所有代码

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值