爬虫第七式:有道翻译破解案例(post)

温馨提示:

爬虫玩得好,监狱进得早。数据玩得溜,牢饭吃个够。

《刑法》第 285 条,非法获取计算机信息系统数据罪。
       违反国家规定,侵入前款规定以外的计算机信息系统或者采用其他技术手段,获取该计算机信息系统中存储、处理或者传输的数据,或者对该计算机信息系统实施非法控制,情节严重的,处三年以下有期徒刑或者拘役,并处或者单处罚金;情节特别严重的,处三年以上七年以下有期徒刑,并处罚金。

正文:

requests.post()

适用场景

1】适用场景 : Post类型请求的网站

【2】参数 : data={}
   2.1) Form表单数据: 字典
   2.2) res = requests.post(url=url,data=data,headers=headers)3】POST请求特点 : Form表单提交数据

控制台抓包

打开方式及常用选项

1】打开浏览器,F12打开控制台,找到Network选项卡

【2】控制台常用选项
   2.1) Network: 抓取网络数据包
     a> ALL: 抓取所有的网络数据包
     b> XHR:抓取异步加载的网络数据包
     c> JS : 抓取所有的JS文件
   2.2) Sources: 格式化输出并打断点调试JavaScript代码,助于分析爬虫中一些参数
   2.3) Console: 交互模式,可对JavaScript中的代码进行测试
    
【3】抓取具体网络数据包后
   3.1) 单击左侧网络数据包地址,进入数据包详情,查看右侧
   3.2) 右侧:
     a> Headers: 整个请求信息
        General、Response Headers、Request Headers、Query String、Form Data
     b> Preview: 对响应内容进行预览
     c> Response:响应内容

有道翻译破解案例(post)

最终的效果,就是运行完控制台的效果:

	# 结果展示
	请输入要翻译的词语: elephant
	翻译结果: 大象
	*************************
	请输入要翻译的词语: 喵喵叫
	翻译结果: mews

接下来我们就看一下抓包的步骤,我们这个有道翻译不仅是post 请求的方式,还是动态数据加载,是json数据类型
比如我们先翻译一个吧
在这里插入图片描述
这个你看我们要是想抓到翻译结果英文在源代码中显示,这是不可能的对吧,这个绝对是一万个没有的:
在这里插入图片描述
而且吧,你翻译完了,你说看IP地址的变化,那也没有变换啊,你说要是有点变化,我们还能捕捉一下它的规律是吧,但这也不会又变化,所以我们只能是F12抓包
如果要抓包,我们就得知道,我们在翻译这段话的时候,客户端和web服务器之间有那些网络数据包的交互,我发的什么请求,返回的又是什么响应,最终返回到页面上,所以我们就直接抓包,点击F12
在这里插入图片描述
刷新一下,点击Network选项卡,因为我们再刷新的时候,我们就可以抓到所有我们可web服务器之间所有交互的数据包
在这里插入图片描述
我们看这三个,解释一下:
ALL:所有的数据包,比如:png、css、js、ajax…
XHR:异步数据包
JS:js文件数据包

我们主要看这三个
接下来我们看ALL里面的这个,因为我们怀疑他就是响应翻译结果的数据包:
在这里插入图片描述
这个就是整个有道翻译的主页,我们点击它
在这里插入图片描述

看这个选项,这个就是post请求数据都在这里,在他的右面我们点开看到这是就是响应页面,中间的Preview就是预览,这个是没有翻译结果的,好了我们这个就是看一下这里面的各个选项的功能作用
接下来我们看看有没有异步的,就是XHR
在这里插入图片描述
我们看到有一条数据包,我们点开它,但是我们也是不知道是不是返回数据的异步包,我们先看Preview
在这里插入图片描述
可以看到啊,有我们翻译的这句话,我们确认了,这就是我们要找的,接下来需要分析一下,我们在Headers中分析,因为它是整个请求的信息啊,,所以我们转到Headers
在这里插入图片描述
接着我们往下看,这两个暂时都不用看呢
在这里插入图片描述
无非你想处理的和浏览器一样,就跟我们headers里面cookie什么的都弄成一样的,接着我们看这个查询参数:
在这里插入图片描述
这个无非就是把请求url里面的 ?后面的东西给你格式化输出了,就是让你好看,好找怎么加密的,就是格式化输出,这个也无所谓了,下一个,就要好好看看了Form Data表单数据:
在这里插入图片描述
这里是我们的翻译的那句话,下面就是发送了框里面的数据到上面url请求地址,最后返回到Preview里,把翻译的结果提出来最终显示在页面中,这就是整个过程,好的接下来就可以这样写代码:

html=requests.post(url=url,data=data,headers=headers).content.decode("utf-8",'ignore')

这个URL就是我们抓包抓到的url,就是上面的截图里面的url,而data就是我们Form Data里面的数据,其他的就是正常走了,其实我们还是没有弄完呢,我们看data数据:
在这里插入图片描述
我们最终是不是要把这个里面的数据定义到字典里面啊,前面还好说,但是我们看这个
在这里插入图片描述
这些应该是类似于一个时间戳的东西把,这每次翻译都是不一样的把,我们看sign这个是一个md5加密的字符串包括下面的bv也是加密的,我们也不知道它是通过什么加密的,你说它是给翻译单词加密?这是猜的,人家不可能给单词加密,因为太简单了,那像这样的东西,就得知道它是怎么生成的把,一般来说它是通过本地JS生成的,但是你要找到是那个js,js里面的哪段代码,再然后它的加密方式是什么样的,再想办法破解,所以我们以后在遇到这种,就要知道进行下一步的分析了
我们接着分析加密那个地方,我们在看翻译一次,对比Form Data里面的数据那些是一样的,那些又是不一样的:
在这里插入图片描述
在这里插入图片描述

通过对比,暂时不看加密的那四个,其他的都一样,那我们在看加密的那四个,出了bv其他的都不一样,那我就知道这个使用了一个固定的字符串,进行md5加密,我们怎么知道是md5加密,因为它是32位,根据固定字符串加密,所以每次都一样
接着我们点开JS的选项卡:找到js文件,因为我们在XHR里面有些东西不知道是怎么生成的,那就只能找js文件了:
在这里插入图片描述
那这个js文件太多了,我们也不知道哪个是怎么办,这时候我们可以直接==Ctrl + Alt + f==搜一下,这样就出现了一个搜索框,我们找那个关键字,就搜sign关键字吧,你搜别的关键字也行,这样就过滤掉一部分js文件,更简单找到包含关键字的js文件结果会显示在下面:
在这里插入图片描述
这个文件就是包含sign关键字的文件,那我们得找到这个文件里面包含关键字的代码段啊,所以我们单击找到的文件:
在这里插入图片描述
这样他就自动跳到Sources选项卡了我们在单击这个花括号,就格式化输出了,方便我们看了
在这里插入图片描述
它就会格式化输出代码方便我们看了:
在这里插入图片描述
我们这个搜到的代码有九千多行,我们只能再次搜关键字sign,直接 Ctrl + f,搜sign会看到有很多,所以我们要看差不多的关键字,有的关键字在路径里面,有的是在变量什么点什么,所以最终我们搜到这里
在这里插入图片描述
大概在8376左右行,这样,也看到了md5加密的,相比别的是会好一点的,起码它像,对吧,好我们接着分析,这样,我们看上面的ts:r,通过 r 找到在上面r = “” + (new Date).getTime()这个东西就是获取时间戳的,如果不知道,那你还是先去学习js吧,那接着我们复制这段代码到Console选项卡中输出一下:
在这里插入图片描述
是不是每个都不一样,这是一个13位的时间戳,当然python也可以生成时间戳,就是这样导入time模块后,输出 str(int(time.time() * 1000)) 这样就是一个13位的时间戳,好多网站其实都有时间戳

接着我们看bv:t 这个 t ,在上面是定义的一个加密定义的变量,后面是n.md5,这个 n 我们也不知道它是什么东西,在上面还有好多n,我们就不知道了,也没有必要了解了,我们就知道,这个n是加密后面的东西,赋值给了 t ,那我们就在Console选项卡中在打印一下这个
在这里插入图片描述
这个打印出来,我们看着很眼熟,这就是User-Agent的一部分吧,所以我们这个对应的bv 是不变的,这个就是对应User-Agent字符串加密的,所以不变,我们也不用管它了
在这里插入图片描述
我们接着看这个salt
在这里插入图片描述
它对应着 i , 这个 i 又被上面的 r 赋值,反正就是各种绕,那个 r 的话,我们刚才说了,就是一个时间戳 ,但是后面又给了这个东西:parseInt(10 * Math.random(), 10), 这个好像是随机数吧,因为它出现了一个random,又出现了数字,但是我们不知道,我们接着 Console:
在这里插入图片描述
这样我们就知道了,他就是一个随机生成0-9的数字,但这个应该是字符串的啊,因为,我们上面的 r 是一个字符串的时间戳,总不能让一个字符串去加数字吧,所以应该也是字符串

所以到现在我们可以发现一个规律,就是这个,图有点乱,但是没办法,下面我在解释:
在这里插入图片描述
我们看 r 是一个13 位的时间戳,也就是ts,是一个13位的时间戳;而这个 salt ,也就是ts 13位的时间戳加上一个0-9的随机数,也就是说,tssalt前13位是一样的也就是最后一位不相同,那我们看一下:
在这里插入图片描述
确实如我们发现的,前13位是相同的,最后一位是不同的
接着我们看sign
在这里插入图片描述
我们看这个图中标注的箭头,这都是固定的字符串不用管,而中间的 i 我们刚才弄明白了,我们主要看这个 e,哎呀完了,好像这个 e 我们不太好去找它是干嘛的了吧,那这时候我们就直接打断点,就在它这行打一个断点,因为这个程序运行到断点的这行就会停,我们好分析它下一步是怎么走的,那次是我们需要再次翻译一个单词,才可以:
在这里插入图片描述
可以看到翻译停止了,通过这样我们就知道,这个 e 就是我们翻译的单词,把鼠标放到e 上:
在这里插入图片描述
能看到这就是我们要翻译的单词,这时候我们就知道了sign 就是它前面的字符串加上e(要翻译的单词) 在加上i(时间戳) ,最后在加一个固定的字符串,对这几个东西进行md5加密,好了我们分析完了,接下来就是写代码了,但是写代码之前我们得对Form Data 里面的数据处理一下,处理成字典,因为里面的东西都是我们写代码的必需品,还有headers里面的参数,也得用浏览器的,所以这两个,我们批量处理一下:
在这里插入图片描述
我们复制里面的东西到pycharm里创建一个文件,放进去:
在这里插入图片描述
在这里插入图片描述
框里面所有的数据,我们处理成这样:
这个是Request Headers里面的,里面有很多东西我们用不到,因为需要严谨一点,嘿嘿,我就全整上了,如果不想整,就只整:Cookie、Referer、User-Agent 就好了
在这里插入图片描述

这个是 Form Data里面的
在这里插入图片描述
注意:

这两个处理成字典的数据保存起来,写代码会用到

1、这两个是用引号引起来的,我这里用的双引号,如果引完,有出红色下划线的,就说明有的数据使用双引号引起来的,那就用三引号
2、引号的后面,不能有空格!!!

接下来我们写代码:

导入模块
import requests
import time
import random
from hashlib import md5   # 加密
import json   # 里面会有用到json串的
定义函数
class YdSpider(object):
  def __init__(self):
    # url一定为F12抓到的 headers -> General -> Request URL
    self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
    # 用到了我们刚刚转的headers字典
    self.headers = {
      # 检查频率最高 - 3个
      "Cookie": "OUTFOX_SEARCH_USER_ID=-441685778@103.102.194.226; OUTFOX_SEARCH_USER_ID_NCOO=1311232133.5140777; _ntes_nnid=a6a6cfcf2f13779cd11ad8e2ca44836d,1595664981237; _ga=GA1.2.1866744817.1598613276; JSESSIONID=aaavr_8IVn9yc9P3to-wx; SESSION_FROM_COOKIE=unknown; ___rl__test__cookies=1605238339474",
      # 这个Referer是指,从哪个网站跳转过来的
      "Referer": "http://fanyi.youdao.com/",
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36",
    }
md5加密函数

不懂得去自行解决一下喽~~

def md5_word(self, string):
    s = md5()
    s.update(string.encode())

    return s.hexdigest()
定义ts、salt、sign

如果忘了这三个是什么了,再去看看上面啊,写这个就是用Python代码,代替js代码

# word就是要翻译的单词,给它传入进去
def get_ts_salt_sign(self, word):
    ts = str(int(time.time() * 1000))
    salt = ts + str(random.randint(0, 9))
    string = "fanyideskweb" + word + salt + "]BjuETDhU)zqSxf-=B#7m"
    sign = self.md5_word(string)
	# 要把这是三个参数都要return出去,因为都得用到
    return ts, salt, sign

最后一个函数:

获取我们定义的ts、salt、sign
def attack_yd(self, word):
    # 获取ts,salt,sign
    ts, salt, sign = self.get_ts_salt_sign(word)
    # 这就是我们刚才的data字典,这里用到了
    data = {
    	# "i": 翻译的单词
        "i": word,
        "from": "AUTO",
        "to": "AUTO",
        "smartresult": "dict",
        "client": "fanyideskweb",
        # 下面三个,换成我们之前定义的
        # salt sign : 一定需要处理
        "salt": salt,
        "sign": sign,
        "lts": ts,
        "bv": "a85763c72b3babd7639e5d3df56ae30c",
        "doctype": "json",
        "version": "2.1",
        "keyfrom": "fanyi.web",
        "action": "FY_BY_REALTlME",
    }
    html = requests.post(url=self.url,
                         data=data,
                         headers=self.headers).text
    # json.loads():json格式字符串转为pyhton数据类型
    # 发起请求
    html = json.loads(html)
    result = html['translateResult'][0][0]['tgt']

    return result
最后程序入口函数,用来控制整体逻辑:
def run(self):
    word = input('请输入翻译的单词:')
    print(self.attack_yd(word))
最后奉上全部代码:
import requests
import time
import random
from hashlib import md5
import json

class YdSpider:
    def __init__(self):
        # url: F12抓包抓到的POST的地址
        self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
        self.headers = {
            # 检查频率最高的三个字段:Cookie Referer User-Agent
            "Cookie": "OUTFOX_SEARCH_USER_ID=-441685778@103.102.194.226; OUTFOX_SEARCH_USER_ID_NCOO=1311232133.5140777; _ntes_nnid=a6a6cfcf2f13779cd11ad8e2ca44836d,1595664981237; _ga=GA1.2.1866744817.1598613276; JSESSIONID=aaavr_8IVn9yc9P3to-wx; SESSION_FROM_COOKIE=unknown; ___rl__test__cookies=1605238339474",
            "Referer": "http://fanyi.youdao.com/",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36",
        }

    def md5_word(self, string):
        """md5加密函数"""
        s = md5()
        s.update(string.encode())

        return s.hexdigest()

    def get_ts_salt_sign(self, word):
        """获取ts salt sign"""
        ts = str(int(time.time() * 1000))
        salt = ts + str(random.randint(0, 9))
        string = "fanyideskweb" + word + salt + "]BjuETDhU)zqSxf-=B#7m"
        sign = self.md5_word(string)

        return ts, salt, sign

    def attack_yd(self, word):
        # 获取ts,salt,sign
        ts, salt, sign = self.get_ts_salt_sign(word)
        data = {
            "i": word,
            "from": "AUTO",
            "to": "AUTO",
            "smartresult": "dict",
            "client": "fanyideskweb",
            # salt sign : 一定需要处理
            "salt": salt,
            "sign": sign,
            "lts": ts,
            "bv": "a85763c72b3babd7639e5d3df56ae30c",
            "doctype": "json",
            "version": "2.1",
            "keyfrom": "fanyi.web",
            "action": "FY_BY_REALTlME",
        }
        html = requests.post(url=self.url,
                             data=data,
                             headers=self.headers).text
        # json.loads():json格式字符串转为pyhton数据类型
        html = json.loads(html)
        result = html['translateResult'][0][0]['tgt']

        return result

    def run(self):
        word = input('请输入翻译的单词:')
        print(self.attack_yd(word))

if __name__ == '__main__':
    spider = YdSpider()
    spider.run()


好了,自己试试吧!

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨旭华 

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值