记录维维的每一篇Hello World

image.png

需要安装的第三方库

  1. pip install requests

使用到的模板/库

  1. import requests
  2. import time
  3. import random
  4. import hashlib
  5. import re

爬取步骤

一、获取请求url以及请求数据

1、前往有道翻译官网https://fanyi.youdao.com/获取,不知道怎么获取可以看【python爬虫】爬取百度翻译,里面有获取步骤,跟着步骤走就可以得到以下数据。
image.png

  1. # 需要的数据
  2. data = {
  3. 'i': '你好',
  4. 'from': 'AUTO',
  5. 'to': 'AUTO',
  6. 'smartresult': 'dict',
  7. 'client': 'fanyideskweb',
  8. 'salt': '16469009309320',
  9. 'sign': '1919a97164a3f49c2f7952950f9fec45',
  10. 'lts': '1646900930932',
  11. 'bv': '8485025d8b016004f09679843317d954',
  12. 'doctype': 'json',
  13. 'version': '2.1',
  14. 'keyfrom': 'fanyi.web',
  15. 'action': 'FY_BY_REALTlME'
  16. }
  17. # 请求url
  18. url = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

二、分析请求数据

1、因为有道翻译有反爬机制,所以需要分析数据,才能使用。
image.png
image.png

2、通过多次的翻译分析后就可以看到(这里只放两张图片展示)数据中:
i 是我们需要翻译的文字,
from 是原文的语言类型,如 cn 表示中文, AUTO是自动识别,
to 是需要目标翻译的语言类型,
lts 是时间戳(需要注意的是,JavaScript的时间戳是以毫秒计算的,我们后期写入的时候需要更改),
salt 是时间戳(lts)加一个随机数字,
sign 是一段通过md5加密的字符,需要分析js文件才能知道怎么生成,
其他参数均不变。

三、分析js文件,得到加密字符

1、打开有道翻译官网: https://fanyi.youdao.com/,按下F12打开工具,查看元素,在上面就可以看到有三个js文件的链接,依次打开,最终确定sign参数是在https://shared.ydstatic.com/fanyi/newweb/v1.1.9/scripts/newweb/fanyi.min.js中生成的。
image.png

2、打开js文件的链接https://shared.ydstatic.com/fanyi/newweb/v1.1.9/scripts/newweb/fanyi.min.js
image.png
3、可以看到,是一段很乱的JavaScript代码,很难从中提取出我们想要的东西,不过也有格式化js代码的网站,百度一下就可以找到,当然,也可以用python快速提取我们想要的字符。

  1. #!../venv/Scripts python
  2. # -*- coding:utf-8 -*-
  3. # Project: get js
  4. # Created by 维维
  5. import requests
  6. import re
  7. def get_signs(url_js: str):
  8. """
  9. 得到加密字符
  10. :param url_js: fanyi.min.js的链接
  11. :return: 匹配到的加密字符
  12. """
  13. header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
  14. "Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.30"}
  15. response = requests.get(url=url_js, headers=header)
  16. response.encoding = 'utf-8'
  17. text = response.text
  18. res = re.search('\"fanyideskweb\"\s?\+\s?[a-zA-Z]\s?\+\s?[a-zA-Z]\s?\+\s?\"(.*?)\"', text, re.S)
  19. try:
  20. return res.group(1)
  21. except AttributeError:
  22. return None
  23. def get_url_js():
  24. """
  25. 得到js代码的请求url
  26. :return: fanyi.min.js的链接
  27. """
  28. url_yd = 'https://fanyi.youdao.com/'
  29. header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
  30. "Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.30"}
  31. response = requests.get(url=url_yd, headers=header)
  32. response.encoding = 'utf-8'
  33. html = response.text
  34. # print(html)
  35. # 正则匹配想要的链接
  36. http_js = re.findall('<script.*?src="(http[s]?://[a-zA-Z0-9./]*fanyi.min.js)"></script>', html)
  37. try:
  38. return http_js[0]
  39. except IndexError:
  40. return None
  41. if __name__ == '__main__':
  42. # js的url
  43. jsUrl = get_url_js()
  44. # 匹配并打印
  45. if jsUrl is not None:
  46. md5Str = get_signs(url_js=jsUrl)
  47. print(md5Str)
  48. else:
  49. print("匹配失败")

四、实现翻译功能

数据齐全,就可以开始实现了,简单实现过程。

  1. #!../venv/Scripts python
  2. # -*- coding:utf-8 -*-
  3. # Project: 有道翻译
  4. # Created by 维维
  5. import requests
  6. import time
  7. import random
  8. import hashlib
  9. def youdao(text):
  10. e = text
  11. timestamp = str(time.time()).replace('.', '')
  12. lts = str(int(timestamp * 1000))
  13. salt = lts + str(random.randint(0, 9))
  14. # md5加密
  15. sign_str = 'fanyideskweb' + e + salt + 'Ygy_4c=r#e#4EX^NUGUc5'
  16. sign = hashlib.md5(sign_str.encode(encoding='UTF-8')).hexdigest()
  17. data = {
  18. 'i': e,
  19. 'from': 'AUTO',
  20. 'to': 'AUTO',
  21. 'smartresult': 'dict',
  22. 'client': 'fanyideskweb',
  23. 'salt': salt,
  24. 'sign': sign,
  25. 'lts': lts,
  26. 'bv': '8485025d8b016004f09679843317d954',
  27. 'doctype': 'json',
  28. 'version': '2.1',
  29. 'keyfrom': 'fanyi.web',
  30. 'action': 'FY_BY_REALTlME'
  31. }
  32. url = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
  33. header = {
  34. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
  35. "Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.30",
  36. 'Cookie': 'OUTFOX_SEARCH_USER_ID=-1154806696@10.168.8.76; \
  37. OUTFOX_SEARCH_USER_ID_NCOO=1227534676.2988937; \
  38. JSESSIONID=aaa7LDLdy4Wbh9ECJb_Vw; ___rl__test__cookies=1563334957868',
  39. 'Referer': 'https://fanyi.youdao.com/'
  40. }
  41. response = requests.post(url, data=data, headers=header)
  42. response.encoding = 'utf-8'
  43. result = response.json()
  44. if result['errorCode'] == 0:
  45. return result['translateResult'][0][0]['tgt']
  46. else:
  47. return text
  48. if __name__ == '__main__':
  49. while True:
  50. text1 = input("你想翻译的原文: ")
  51. if text1 == 'q':
  52. break
  53. text2 = youdao(text1)
  54. print("原文: ", text1, "\n翻译: ", text2, end='\n\n')

完整源码

  1. #!../venv/Scripts python
  2. # -*- coding:utf-8 -*-
  3. # Project: 有道翻译
  4. # Created by 维维
  5. import requests
  6. import time
  7. import random
  8. import hashlib
  9. import re
  10. class Youdao:
  11. def __init__(self):
  12. """
  13. 爬取有道翻译,实现翻译功能
  14. """
  15. self.__i = ''
  16. self.__from = 'AUTO'
  17. self.__to = 'AUTO'
  18. self.__url = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
  19. self.__url1 = 'https://fanyi.youdao.com/'
  20. self.__header = {
  21. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
  22. "Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.30",
  23. 'Cookie': 'OUTFOX_SEARCH_USER_ID=-1154806696@10.168.8.76; \
  24. OUTFOX_SEARCH_USER_ID_NCOO=1227534676.2988937; \
  25. JSESSIONID=aaa7LDLdy4Wbh9ECJb_Vw; ___rl__test__cookies=1563334957868',
  26. 'Referer': 'https://fanyi.youdao.com/'
  27. }
  28. self.__sleep_second = 3
  29. self.__signs = self.__get_signs()
  30. self.__doc__ = "爬取有道翻译,实现翻译功能,仅作为学习使用"
  31. @property
  32. def url(self):
  33. """
  34. 有道翻译官网
  35. """
  36. return self.__url
  37. @property
  38. def header(self):
  39. """
  40. 请求头
  41. """
  42. return self.__header
  43. def set_sleep_second(self, second: int):
  44. """
  45. 设置出现错误时停留时间(s)
  46. :param second: 停留时间
  47. """
  48. self.__sleep_second = second
  49. def set_from_to(self, f: str, t: str):
  50. """
  51. 设置原文和翻译语言类型,默认为AUTO
  52. :param f: 原文语言类型
  53. :param t: 翻译语言类型
  54. """
  55. self.__from = f
  56. self.__to = t
  57. def __get_signs(self):
  58. """
  59. 得到sign中的加密字符
  60. :return: 加密字符
  61. """
  62. response = requests.get(url=self.__url1, headers=self.__header)
  63. # 正则匹配想要的链接
  64. http_js = re.findall('<script.*?src="(http[s]?://[a-zA-Z0-9./]*fanyi.min.js)"></script>', response.text)
  65. try:
  66. response1 = requests.get(url=http_js[0], headers=self.__header)
  67. except IndexError as ie:
  68. print("IndexError:", ie)
  69. time.sleep(self.__sleep_second)
  70. self.__get_signs()
  71. res = re.search('\"fanyideskweb\"\s?\+\s?[a-zA-Z]\s?\+\s?[a-zA-Z]\s?\+\s?\"(.*?)\"', response1.text, re.S)
  72. try:
  73. return res.group(1)
  74. except AttributeError as ae:
  75. print("AttributeError:", ae)
  76. time.sleep(self.__sleep_second)
  77. self.__get_signs()
  78. def __translate(self):
  79. """
  80. 翻译实例
  81. """
  82. timestamp = time.time()
  83. lts = str(int(timestamp * 1000))
  84. salt = lts + str(random.randint(0, 9))
  85. signs = 'fanyideskweb' + self.__i + salt + self.__signs
  86. sign = hashlib.md5(signs.encode(encoding='UTF-8')).hexdigest()
  87. data = {
  88. 'i': self.__i,
  89. 'from': self.__from,
  90. 'to': self.__to,
  91. 'smartresult': 'dict',
  92. 'client': 'fanyideskweb',
  93. 'salt': salt,
  94. 'sign': sign,
  95. 'lts': lts,
  96. 'bv': '8485025d8b016004f09679843317d954',
  97. 'doctype': 'json',
  98. 'version': '2.1',
  99. 'keyfrom': 'fanyi.web',
  100. 'action': 'FY_BY_REALTlME'
  101. }
  102. response = requests.post(url=self.__url, data=data, headers=self.__header)
  103. response.encoding = 'utf-8'
  104. result = response.json()
  105. self.__result = result['translateResult'][0][0]['tgt'] if result['errorCode'] == 0 else ''
  106. def translate(self, string: str) -> str:
  107. """
  108. 翻译功能
  109. :param string: 需要翻译的原文
  110. :return: 翻译的内容
  111. """
  112. self.__i = string
  113. self.__translate()
  114. return self.__result
  115. def translate_show(self, string: str):
  116. """
  117. 翻译并打印
  118. :param string: 需要翻译的原文
  119. """
  120. self.__i = string
  121. self.__translate()
  122. if self.__result == '':
  123. print(string)
  124. else:
  125. print(self.__result)
  126. if __name__ == '__main__':
  127. # 需要翻译的内容
  128. s = '人生苦短,我用python'
  129. print(s)
  130. # 实例化
  131. yd = Youdao()
  132. # 翻译并打印
  133. yd.translate_show(string=s)
  134. # 打印有道官网
  135. # print(yd.url)

python环境

电脑:Windows10

python:3.8.8(建议3.7以上)