当前位置:   article > 正文

Python3爬取有道翻译的两种方法

Python3爬取有道翻译的两种方法

一. 破解参数加密

有道翻译的请求是post,携带一系列参数,直接F12刷新进行调试,如下图所示:

这是一个 post 请求,目标网址是

'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

接下来让我们看看发送该请求需要携带哪些参数

如图所示,红色方框里的就是需要携带的参数了。

最后看一看返回的数据

显而易见,返回的数据是json格式的数据。

好了,现在我们可以写程序进行爬取了

  1. # -*-coding:utf-8-*-
  2. __Author__ = "Mr.D"
  3. __Date__ = '2019\5\26 0026 16:50'
  4. from faker import Faker
  5. import requests
  6. ua = Faker().user_agent()
  7. url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
  8. key = input("请输入你需要翻译的内容: ")
  9. # 请求头
  10. headers = {
  11. 'User-Agent': ua,
  12. 'Host': 'fanyi.youdao.com',
  13. 'Origin': 'http://fanyi.youdao.com',
  14. 'Referer': 'http://fanyi.youdao.com/',
  15. }
  16. # post请求携带的参数
  17. from_data = {
  18. 'i': key,
  19. 'from': 'UTO',
  20. 'to': 'UTO',
  21. 'smartresult': 'dict',
  22. 'client': 'fanyideskweb',
  23. 'salt': 15588802331547,
  24. 'sign': 3e91f2d8788201c03bfa0a672b116998,
  25. 'ts': 1558880233154,
  26. 'bv': '5504a5c7c19867a06038cf79d29f756a',
  27. 'doctype': 'json',
  28. 'version': '2.1',
  29. 'keyfrom': 'fanyi.web',
  30. 'action': 'FY_BY_REALTlME'
  31. }
  32. response = requests.post(url, headers=headers, data=from_data).json()
  33. print(response)
  34. print(response['translateResult'][0][0]['tgt'])

运行后发现报错了,"{errorCode: 50}"

什么原因呢? 让我们分析一下。

可以自己 重新来翻译一下  "问题" 这个词,然后在看一次此次 post 请求与上一次 post 请求有什么不同之处。

经过调试,我发现 from_data 中的参数有几个是发生了变化的,分别是 "salt","sign","ts",那么这几个参数是怎么生存的呢?

经过寻找,发现它们的生存规律在 "http://shared.ydstatic.com/fanyi/newweb/v1.0.17/scripts/newweb/fanyi.min.js" 这个  js 文件中,经过 json 格式化工具(百度)格式化之后,定位到具体的参数生成位置,

  1. // e 为下面 r(t) 中的 t ,即我们所需要翻译的内容
  2. var r = function(e) {
  3. var t = n.md5(navigator.appVersion),
  4. r = "" + (new Date).getTime(),
  5. i = r + parseInt(10 * Math.random(), 10);
  6. return {
  7. ts: r,
  8. bv: t,
  9. salt: i,
  10. sign: n.md5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj")
  11. }
  12. };
  13. t.recordUpdate = function(e) {
  14. // 将我们所要翻译的内容赋值给 t
  15. var t = e.i,
  16. // 将 t 当作参数传入 r() 函数中,返回值赋给 i
  17. i = r(t);
  18. n.ajax({
  19. type: "POST",
  20. contentType: "application/x-www-form-urlencoded; charset=UTF-8",
  21. url: "/bettertranslation",
  22. // 这里可以看出 data 就是我们post请求携带的参数字典
  23. data: {
  24. // e.i 就是我们所要翻译的内容
  25. i: e.i,
  26. client: "fanyideskweb",
  27. salt: i.salt,
  28. sign: i.sign,
  29. ts: i.ts,
  30. bv: i.bv,
  31. tgt: e.tgt,
  32. modifiedTgt: e.modifiedTgt,
  33. from: e.from,
  34. to: e.to
  35. },
  36. success: function(e) {},
  37. error: function(e) {}
  38. })
  39. }

从上述代码中,我们可以得出四个参数的信息: ts,bv,salt,sign,他们分别为

  1. ts: "" + (new Date).getTime(),
  2. bv: n.md5(navigator.appVersion),
  3. salt: ts + parseInt(10 * Math.random(), 10),
  4. // e为所需要翻译的字符串, i 即salt
  5. sign: n.md5("fanyideskweb" + e + salt + "n%A-rKaT5fb[Gy?;N5@Tj")

分析一波:

bv 是对  navigator.appVersion(这是个浏览器参数,不是字符串"navigator.appVersion")进行 md5 加密,在相同的浏览器下,这个值是固定的(没测试过),所以直接拿F12调试出来的来用就好了。

ts 是时间戳

salt 是 ts 加上一个 0 到 10 的随机数(包括0,不包括10)

sign 是对 "fanyideskweb" + e + salt + "n%A-rKaT5fb[Gy?;N5@Tj" (这个字符串是会更新的,在js文件里可以找到)这个字符串进行 md5 加密

好了,知道以上信息,我们可以进一步完善我们的代码了,如下图:

  1. # -*-coding:utf-8-*-
  2. __Author__ = "Mr.D"
  3. __Date__ = '2019\5\26 0026 16:50'
  4. import time
  5. from faker import Faker
  6. import random
  7. import hashlib
  8. import requests
  9. ua = Faker().user_agent()
  10. url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
  11. key = input("请输入你需要翻译的内容: ")
  12. //生成时间戳 ts
  13. ts = str(time.time() * 1000)
  14. // 通过 ts 加 0-10的随机整数字符生成 salt
  15. salt = ts + str(random.randint(0, 10))
  16. the_str = "fanyideskweb" + key + salt + "n%A-rKaT5fb[Gy?;N5@Tj"
  17. // md5加密生成 sign
  18. md5 = hashlib.md5()
  19. md5.update(the_str.encode('utf-8'))
  20. sign = md5.hexdigest()
  21. headers = {
  22. 'User-Agent': ua,
  23. 'Host': 'fanyi.youdao.com',
  24. 'Origin': 'http://fanyi.youdao.com',
  25. 'Referer': 'http://fanyi.youdao.com/',
  26. }
  27. from_data = {
  28. 'i': key,
  29. 'from': 'UTO',
  30. 'to': 'UTO',
  31. 'smartresult': 'dict',
  32. 'client': 'fanyideskweb',
  33. 'salt': salt,
  34. 'sign': sign,
  35. 'ts': ts,
  36. 'bv': '5504a5c7c19867a06038cf79d29f756a',
  37. 'doctype': 'json',
  38. 'version': '2.1',
  39. 'keyfrom': 'fanyi.web',
  40. 'action': 'FY_BY_REALTlME'
  41. }
  42. response = requests.post(url, headers=headers, data=from_data).json()
  43. print(response)
  44. print(response['translateResult'][0][0]['tgt'])

完成之后再次爬取,发现还是报一样的错误。

纳尼!! 再三检查代码,没有发现有写错任何地方啊

既然  from_data 没有写错,那么问题可能是出现在了 headers 上了

经过调试,发现每次 headers 都会携带 cookie ,而且 cookie 的值每次都不一样

'Cookie': 'OUTFOX_SEARCH_USER_ID=559238864@10.168.8.61; OUTFOX_SEARCH_USER_ID_NCOO=2061523511.1027195; _ga=GA1.2.1151109878.1551536968; _ntes_nnid=24fe647fc20f952c4040b25650f75604,1553001083850; JSESSIONID=aaaJIa27BLmlI96aStZRw; ___rl__test__cookies=1558881656766'

不一样的地方在于最后的那个 "__rl__test__cookies=" 后面的字符串不一样,然后去找到它是怎么生成的,最后终于在

"http://shared.ydstatic.com/js/rlog/v1.js" 这个js文件中找到了它

原来它也是时间戳,怪不得看起来有点像

继续完善代码

  1. # -*-coding:utf-8-*-
  2. __Author__ = "Mr.D"
  3. __Date__ = '2019\5\26 0026 16:50'
  4. import time
  5. from faker import Faker
  6. import random
  7. import hashlib
  8. import requests
  9. ua = Faker().user_agent()
  10. url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
  11. key = input("请输入你需要翻译的内容: ")
  12. //生成时间戳 ts
  13. ts = str(time.time() * 1000)
  14. // 通过 ts 加 0-10的随机整数字符生成 salt
  15. salt = ts + str(random.randint(0, 10))
  16. the_str = "fanyideskweb" + key + salt + "@6f#X3=cCuncYssPsuRUE"
  17. // md5加密生成 sign
  18. md5 = hashlib.md5()
  19. md5.update(the_str.encode('utf-8'))
  20. sign = md5.hexdigest()
  21. headers = {
  22. 'User-Agent': ua,
  23. 'Host': 'fanyi.youdao.com',
  24. 'Origin': 'http://fanyi.youdao.com',
  25. 'Referer': 'http://fanyi.youdao.com/',
  26. 'Cookie': 'OUTFOX_SEARCH_USER_ID=559238864@10.168.8.61; OUTFOX_SEARCH_USER_ID_NCOO=2061523511.1027195; _ga=GA1.2.1151109878.1551536968; _ntes_nnid=24fe647fc20f952c4040b25650f75604,1553001083850; JSESSIONID=aaaJIa27BLmlI96aStZRw; ___rl__test__cookies=' + ts
  27. }
  28. from_data = {
  29. 'i': key,
  30. 'from': 'UTO',
  31. 'to': 'UTO',
  32. 'smartresult': 'dict',
  33. 'client': 'fanyideskweb',
  34. 'salt': salt,
  35. 'sign': sign,
  36. 'ts': ts,
  37. 'bv': '5504a5c7c19867a06038cf79d29f756a',
  38. 'doctype': 'json',
  39. 'version': '2.1',
  40. 'keyfrom': 'fanyi.web',
  41. 'action': 'FY_BY_REALTlME'
  42. }
  43. response = requests.post(url, headers=headers, data=from_data).json()
  44. print(response)
  45. print(response['translateResult'][0][0]['tgt'])

好了,让我们运行代码看看

大功告成。

附使用 urllib 库的代码
 

  1. # -*-coding:utf-8-*-
  2. __Author__ = "Mr.D"
  3. __Date__ = '2019\5\26 0026 18:07'
  4. import urllib.request
  5. import urllib.parse
  6. import json
  7. import time
  8. import random
  9. import hashlib
  10. from faker import Faker
  11. url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
  12. ua = Faker().user_agent()
  13. key = input("请输入你需要翻译的内容: ")
  14. ts = str(time.time() * 1000)
  15. salt = ts + str(random.randint(0, 10))
  16. the_str = "fanyideskweb" + key + salt + "@6f#X3=cCuncYssPsuRUE"
  17. md5 = hashlib.md5()
  18. md5.update(the_str.encode('utf-8'))
  19. sign = md5.hexdigest()
  20. # 请求头
  21. headers = {
  22. 'User-Agent': ua,
  23. 'Host': 'fanyi.youdao.com',
  24. 'Origin': 'http://fanyi.youdao.com',
  25. 'Referer': 'http://fanyi.youdao.com/',
  26. 'Cookie': 'OUTFOX_SEARCH_USER_ID=559238864@10.168.8.61; OUTFOX_SEARCH_USER_ID_NCOO=2061523511.1027195; _ga=GA1.2.1151109878.1551536968; _ntes_nnid=24fe647fc20f952c4040b25650f75604,1553001083850; JSESSIONID=aaaJIa27BLmlI96aStZRw; ___rl__test__cookies=' + ts
  27. }
  28. # 表单数据
  29. from_data = {
  30. 'i': key,
  31. 'from': 'UTO',
  32. 'to': 'UTO',
  33. 'smartresult': 'dict',
  34. 'client': 'fanyideskweb',
  35. 'salt': salt,
  36. 'sign': sign,
  37. 'ts': ts,
  38. 'bv': '5504a5c7c19867a06038cf79d29f756a',
  39. 'doctype': 'json',
  40. 'version': '2.1',
  41. 'keyfrom': 'fanyi.web',
  42. 'action': 'FY_BY_REALTlME'
  43. }
  44. from_data = urllib.parse.urlencode(from_data).encode('utf-8')
  45. request = urllib.request.Request(url, from_data, headers)
  46. response = urllib.request.urlopen(request).read().decode("utf-8")
  47. target = json.loads(response)
  48. result = target['translateResult'][0][0]['tgt']
  49. print(result)

总结

用到的知识点:

1. faker库随机生成 ua

2. time()函数生成时间戳

3. hashlib库进行md5加密

4. js基础知识的掌握

5. requests库的使用

其中,第四点最为重要

 

二.绕过js加密

代码这个方法非常简单,只需要将 url 中的 _o 去掉就可以了,在传递的from_data中不再需要上述几个加密的参数,只需要我们所要翻译的内容 就可以进行数据获取了

urllib 库的爬取代码如下

  1. # -*-coding:utf-8-*-
  2. __Author__ = "Mr.D"
  3. __Date__ = '2019\5\26 0026 18:07'
  4. import urllib.request
  5. import urllib.parse
  6. import json
  7. from faker import Faker
  8. // 去掉_o
  9. url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
  10. ua = Faker().user_agent()
  11. key = input("请输入你需要翻译的内容: ")
  12. # 请求头
  13. headers = {
  14. 'User-Agent': ua,
  15. 'Host': 'fanyi.youdao.com',
  16. 'Origin': 'http://fanyi.youdao.com',
  17. 'Referer': 'http://fanyi.youdao.com/',
  18. }
  19. # 表单数据
  20. from_data = {
  21. 'i': key,
  22. 'from': 'UTO',
  23. 'to': 'UTO',
  24. 'smartresult': 'dict',
  25. 'client': 'fanyideskweb',
  26. 'doctype': 'json',
  27. 'version': '2.1',
  28. 'keyfrom': 'fanyi.web',
  29. 'action': 'FY_BY_REALTlME'
  30. }
  31. from_data = urllib.parse.urlencode(from_data).encode('utf-8')
  32. request = urllib.request.Request(url, from_data, headers)
  33. response = urllib.request.urlopen(request).read().decode("utf-8")
  34. target = json.loads(response)
  35. result = target['translateResult'][0][0]['tgt']
  36. print(result)

 

在看完上面的代码之后,可以自己尝试着写出使用第二种方法和requests库进行有道翻译的爬取,来验证代码是否正确

最后,欢迎大家提问

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/855669
推荐阅读
相关标签
  

闽ICP备14008679号