python爬虫入门 ✦ 某度翻译

此博客仅为我业余记录文章所用,发布到此,仅供网友阅读参考,如有侵权,请通知我,我会删掉。

打铁趁热,姊妹篇传送门:python爬虫入门 ✦ 某道翻译

1.本文思路

1.先从抓包里面Network—XHR里面的formdata表单分析,需要获取的参数为sign和token。
2.复制sign或token关键字在右上角的search搜索,抓取相关的JS文件
3.将找到的 生成sign或token的函数代码 直接保存到本地文件,利用execjs模块执行js代码,进行调试,从而找出规律
4.通过分析得出 sign和token的值在网页源代码可以请求得到。

1.1 分析url

本次文章链接为 aHR0cHMlM0EvL2ZhbnlpLmJhaWR1LmNvbS8=(base64解密即可)
(1) 在某度翻译页面,点击F12—Network—XHR,然后在输入框输入 student(任意输入),查看抓包到的数据,可以看到一个名为v2transapi的包,点击它,查看Preview。确定了这个是我们最终需要获取的数据包。下面就着手去获取它。
在这里插入图片描述
(2) 接下来我们的移动到headers这里,可以看到响应内容的url,该请求方法为post,下面的画框的Form_Data就是我们所需要的分析的表单内容啦。
在这里插入图片描述
在这里插入图片描述
(3) 来分析一下 student和teacher的Form_Data表单。
通过比对两组表单数据,sign和token(token虽然不变,但是也找出来最好)是我们所需要获取的数据。query则为我们输入需要的翻译的单词,接下来我们看一下如果获取sign,token这两个参数。

from: en	## student
to: zh
query: student
transtype: realtime
simple_means_flag: 3
sign: 767469.1005276
token: 3d154702e04333770e2c6be7c28b0d53
from: en	## teacher
to: zh
query: teacher
transtype: enter
simple_means_flag: 3
sign: 384259.81458
token: 3d154702e04333770e2c6be7c28b0d53

1.2 获取js

(1) 点击该页面右上角,然后点击search,会弹出下图这个界面。然后再在搜索框输入关键字 sign:,选择弹出的第一个。最后点击画红色框框的花括号,(它的作用是将代码格式化,变得好看。)
在这里插入图片描述

(2) 因为代码很长,很难看懂。这个时候只有选择打断点 来分析一下。
可以看到,js代码很长。 这里的sign = 函数m(a),在下面划红框处,打上两个断点,然后再输入框输入任意单词,查看现象。看到我们的函数值m(a)中的a就是我们所输入的单词
在这里插入图片描述
(3) 将鼠标轻轻移动到sign: m(a)这里,可以看到会弹出一个 **f e(r)**的函数,鼠标左键点击它。然后会跳转到该js函数所在的代码行。
在这里插入图片描述
(4) 仔细看一下这个图片画框的地方, 然后对比一下前面的 student 中的 sign:767469.1005276,下图画框的中间那个 “.” 对应的就是 sign的值中间的 "."
在这里插入图片描述
(5) 可是js代码超长,看不懂。这个时候我们就需要将 与 sign相关的代码块复制下来,保存到本地。
在这里插入图片描述

1.3 解析js

(1) 将前面的那一串js代码保存为js格式的文件。
在这里插入图片描述
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
!!!!!
这个时候,解析js代码的 execjs模块要登场了!下面的代码是execjs的简单使用。

import execjs

# 打开刚才保存的baidu.js的文件
with open('baidu.js', 'r') as f:
    js = f.read()

# 创建对象
js_data = execjs.compile(js)

# eval的作用是将字符串当成表达式来执行
sign = js_data.eval('e("student")')	#e是js代码的函数e,student为输入的单词
print(sign)

(2) ??? 报错了?? 看了报错内容为 i未定义。这个时候就去 刚才保存的baidu.js里面找原因。
在这里插入图片描述
(3) 找 i,找 i, 找i。。因为是i报错了。!!!
看到 i了。这里的 U = i = window[ l],而这个 l又等于i = “” “”+ String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107)。。这个时候将这一串编码代码复制到F12—source里面看一下是什么。
在这里插入图片描述
(4) 可以看到,我们复制过来的一串长长的编码代码,解码后为 gtk 所以我们的U = i = window[ gtk], 这个时候去网页源代码搜索一下window[ gtk]。在这里插入图片描述
(5) 可以看到window[ gtk]为一串长长的数字320305.131321201,现在我们将这一串数字复制到 baidu.js里面
在这里插入图片描述
(6) 因为U = i = window[ gtk]=‘320305.131321201’,所以直接就将这串数字赋值给U
在这里插入图片描述
(7) 再次执行我们的代码,嗯。有成功打印结果了!!!!!这一串打印出来的数字是不是很熟悉呢。。返回前面看一下,是不是和我们的 student的Form_Data里面的sign值一样呢!!好,那现在我们就成功解决了这个sign了,接下来就是获取token了。

from: en	## student
to: zh
query: student
transtype: realtime
simple_means_flag: 3
sign: 767469.1005276
token: 3d154702e04333770e2c6be7c28b0d53

在这里插入图片描述
(8) 再次回到js代码,看到token的值为 window.common.token。好家伙,我们就这一串代码去网页源代码搜索一下看看。
在这里插入图片描述
(9) 看到token了。到了现在,我们的js分析已经完成了。代码也相当于完成99%了!
在这里插入图片描述

2.完整代码

import re
import execjs
import requests


class BaiuSpider(object):
    def __init__(self):
        self.base_url = 'https://fanyi.baidu.com'
        self.translate = 'https://fanyi.baidu.com/v2transapi'
        self.headers = {
            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'accept-encoding': 'gzip, deflate, br',
            'accept-language': 'zh-CN,zh;q=0.9',
            'cache-control': 'max-age=0',
            'cookie': 'cookie填写自己的',
            'referer': 'https://fanyi.baidu.com/',
            'upgrade-insecure-requests': '1',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
        }

    def get_token_gtk(self):
        res = requests.get(self.base_url, headers=self.headers).text
        token = re.findall("window.*?token: '(.*?)'", res, re.S)
        gtk = re.findall("window.gtk = '(.*?)';</script>", res, re.S)
        print(gtk[0], token[0])
        return token[0], gtk[0]

    def get_sign(self, word, token):
        with open('baidu.js', 'r') as f:
            js = f.read()
        js_data = execjs.compile(js)
        sign = js_data.eval('e("{}","{}")'.format(word, token))
        return sign

    def main(self, word, fro, to):
        token, gtk = self.get_token_gtk()
        sign = self.get_sign(word, gtk)
        form_data = {
            'from': fro,
            'to': to,
            'query': word,
            'transtype': 'realtime',
            'simple_means_flag': '3',
            'sign': sign,
            'token': token
        }
        res = requests.post(self.translate, data=form_data, headers=self.headers).json()
        # print(res)
        print(res['trans_result']['data'][0]['dst'])


if __name__ == '__main__':
    spider = BaiuSpider()
    choice = input("1.英译汉  2.汉译英:")
    word = input("请输入你要翻译的单词:")
    if choice == '1':
        fro, to = 'en', 'zh'
    elif choice == '2':
        fro, to = 'zh', 'en'

    spider.main(word, fro, to)

文章很长,难免有出错的地方,恳请各位为我指正错误。
有不懂的地方欢迎在下方留言或一起讨论。

发布了34 篇原创文章 · 获赞 210 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_45081575/article/details/99702954
今日推荐