鱼C论坛

 找回密码
 立即注册
查看: 1461|回复: 2

[已解决]python爬虫有道翻译:post响应相关问题

[复制链接]
发表于 2021-10-6 16:14:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 非凡 于 2021-10-6 16:25 编辑

我在C语言中文网读到一篇文章,讲爬虫有道翻译
http://c.biancheng.net/python_spider/case05.html
我截取以下一段内容:

通过控制台抓包,我们得知了 POST 请求的参数以及相应的参数值,如下所示:
1.jpg
并发现以下了规律:salt、sign、lts 总是变化的,而 bv 等其他参数是不变化的。其中 lts 代表毫秒时间戳,salt 和 lts 之间存在着某种关联,因为两者只有最后一个数字是不同的;而 sign 对应的值是一个加密后的字符串。

如果想要实现实时地抓取翻译结果,就需要将 salt 和 sign 转换为 用 Python 代码表示的固定形式。最后将所有参数放入到 requests.post() 中,如下所示:
  1. response = requests.post(url,data=data,headers=headers)
复制代码

其中 data 是字典格式参数,它用来构建 POST 请求方法的参数和参数值。

接下来一段是如何寻找页面上的JS代码salat与sign,与我需要解决问题无多大关系,就不复制过来了,感兴趣可以访问原链接。
2.jpg
通过上述方法就找到了 salt 与 sign(两个参数项是在一起的)JS 代码,如下所示:
  1. var r = function(e) {
  2.     var t = n.md5(navigator.appVersion),
  3.     r = "" + (new Date).getTime(),
  4.     i = r + parseInt(10 * Math.random(), 10);
  5.     return {
  6.         ts: r,
  7.         bv: t,
  8.         salt: i,
  9.         sign: n.md5("fanyideskweb" + e + i + "Tbh5E8=q6U3EXe+&L[4c@")
  10.     }
  11. };
复制代码

通过上述 JS 代码的简单分析可知: r 变量等同于 lts,salt 变量等同于 i,而 sign 是一个经过 md5 加密的字符串。接下来使用 Python 代码来表示上述参数,如下所示:

  1. #lts毫秒时间戳
  2. str(int(time.time()*1000))
  3. #salt, lts+从0-9的随机数
  4. lts+str(random.randint(0,9))
  5. #sign加密字符串
  6. from hashlib import md5
  7. #word为要翻译的单词等同于js代码中的"e"
  8. string = "fanyideskweb" + word + salt + "Tbh5E8=q6U3EXe+&L[4c@"
  9. s = md5()
  10. #md5的加密串必须为字节码
  11. s.update(string.encode())
  12. #16进制加密
  13. sign = s.hexdigest()
复制代码

文章中的完整程序实现代码是:

  1. #coding:utf8
  2. import random
  3. import time
  4. from hashlib import md5
  5. import requests


  6. class YoudaoSpider(object):
  7.     def __init__(self):
  8.         # url一定要写抓包时抓到的POST请求的提交地址,但是还需要去掉 url中的“_o”,
  9.         # “_o”这是一种url反爬策略,做了页面跳转,若直接访问会返回{"errorCode":50}
  10.         self.url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
  11.         self.headers={
  12.         "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
  13.         }
  14.     # 获取lts时间戳,salt加密盐,sign加密签名
  15.     def get_lts_salt_sign(self,word):
  16.         lts=str(int(time.time()*1000))
  17.         salt=lts+str(random.randint(0,9))
  18.         string = "fanyideskweb" + word + salt + "Tbh5E8=q6U3EXe+&L[4c@"
  19.         s=md5()
  20.         s.update(string.encode())
  21.         sign=s.hexdigest()
  22.         print(lts,salt,sign)
  23.         return lts,salt,sign

  24.     def attack_yd(self,word):
  25.         lts,salt,sign=self.get_lts_salt_sign(word)

  26.         #构建form表单数据
  27.         data={
  28.             "i": word,
  29.             "from": "AUTO",
  30.             "to": "AUTO",
  31.             "smartresult": "dict",
  32.             "client": "fanyideskweb",
  33.             "salt": salt,
  34.             "sign": sign,
  35.             "lts": lts,
  36.             "bv": "cda1e53e0c0eb8dd4002cefc117fa588",
  37.             "doctype": "json",
  38.             "version": "2.1",
  39.             "keyfrom": "fanyi.web",
  40.             "action": "FY_BY_REALTlME"
  41.         }
  42.         #使用 reqeusts.post()方法提交请求
  43.         res = requests.post(
  44.             url=self.url,
  45.             data=data,
  46.             headers=self.headers,

  47.         )
  48.         # res.json() 将json格式的字符串转为python数据类型
  49.         # 客户端与服务器数据交互以json字符串传递,因此需要将它转换为python数据类型
  50.         html=res.json()
  51.         print(html)
  52.         # 查看响应结果response  html:{"translateResult":[[{"tgt":"hello","src":"你好"}]],"errorCode":0,"type":"zh-CHS2en"}
  53.         result=html["translateResult"][0][0]["tgt"]
  54.         print('翻译结果:', result)

  55.     def run(self):
  56.         try:
  57.             word=input('请输入要翻译的单词:')
  58.             self.attack_yd(word)
  59.         except Exception as e:
  60.             print(e)

  61. if __name__ == '__main__':
  62.     spider=YoudaoSpider()
  63.     spider.run()
复制代码


关于爬虫爬有道翻译,我在小甲鱼的视频里也看过,但是不同的地方是,关于post里的data集,小甲鱼视频里似乎没像上面一样去考虑salt,sign,lts三个参数的变化问题,直接是将网页里的post响应里的原样复制进去就行了,我操作过,代码如下:
  1. import urllib.request
  2. import urllib.parse
  3. import json
  4. content = input('请输入需要翻译的内容:')
  5. url = 'https://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'

  6. data = {}
  7. data['i'] = content
  8. data['from']= 'AUTO'
  9. data['to']= 'AUTO'
  10. data['smartresult']= 'dict'
  11. data['client']= 'fanyideskweb'
  12. #此处的salt、sign、lts三个参数值没有变化
  13. data['salt']= '16315470681987'
  14. data['sign']= 'd6b63a7371c65430a325ca72e9cef1dd'
  15. data['lts']= '1631547068198'
  16. data['bv']= '5912a9bc00e8093f5992b73a3708e1b5'
  17. data['doctype']= 'json'
  18. data['version']= '2.1'
  19. data['keyfrom']= 'fanyi.web'
  20. data['action']= 'FY_BY_CLICKBUTTION'

  21. data = urllib.parse.urlencode(data).encode('utf-8')   # encode('utf-8')将 Unicode 编码转换成utf-8形式


  22. # 修改headers信息User-Agent参数的  方法一:
  23.     # 建立head字典,将User-Agent的值修改未正常浏览器访问网页是用的值()
  24. head = {}
  25. head['User-Agent'] ='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 Edg/93.0.961.47'
  26. req = urllib.request.Request(url,data,head)             #在Request时传入head参数


  27. # 修改headers信息User-Agent参数的  方法二:
  28. req = urllib.request.Request(url,data)
  29.     #通过add_header()追加head参数
  30. req.add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 Edg/93.0.961.47')

  31. response = urllib.request.urlopen(req)

  32. html = response.read().decode('utf-8')          #以utf-8去解码,转换成 Unicode 编码( Unicode 编码是python的默认编码格式)

  33. print(html)             #此时的html是个字符串,是给json语句的字符串


  34. target = json.loads(html)       #将字符串载入

  35. 原文 = target['translateResult'][0][0]['src']
  36. 译文 = target['translateResult'][0][0]['tgt']
  37. print(原文+':'+译文)
复制代码


两段代码实现的效果是一样的,这是为什么?
salt、sign、lts三个参数值在网页中确实每次都是变化的,为什么用代码去爬的时候又不需要去考虑它的变化也能爬成功呢?
最佳答案
2021-10-6 18:26:23
虽然浏览器根据js提交了其他参数,然而参数有没有用,有没有被web服务器用来做校验或授权,这个要看服务器侧的设置。
就目前的现象看,对于有道翻译,我们只需要提交数据中的i即可,其他无从可知。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-10-6 18:26:23 | 显示全部楼层    本楼为最佳答案   
虽然浏览器根据js提交了其他参数,然而参数有没有用,有没有被web服务器用来做校验或授权,这个要看服务器侧的设置。
就目前的现象看,对于有道翻译,我们只需要提交数据中的i即可,其他无从可知。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-7 11:03:23 | 显示全部楼层
suchocolate 发表于 2021-10-6 18:26
虽然浏览器根据js提交了其他参数,然而参数有没有用,有没有被web服务器用来做校验或授权,这个要看服务器 ...

感谢回答
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-15 23:11

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表