由于从接触python到爬完只用了三四个小时(python语法真的超简单啊),而且我并不是从事网页相关工作,部分术语可能不对,烦请指出 :)
环境
浏览器: Chrome
操作系统:Win7
依赖库:python自带,requests
前置知识点
python 基础语法
java script基础语法
json
md5
思路
找到点击翻译时发送的表单数据结构
找到加密算法
问题解决
具体步骤
打开有道翻译网页,按F12,输入 德莉莎世界第一可爱 ,拿到这一次的数据并分析
拿到网址
关键在于Request Headers和FormData
现将Headers和FormData转换成Python的数据结构(字典)
对应代码:
headers ={
'Accept': 'application/json, text/javascript, */*; q=0.01', \
'Accept-Encoding': 'gzip, deflate', \
'Accept-Language': 'en,zh-CN;q=0.9,zh;q=0.8', \
'Connection': 'keep-alive', \
'Content-Length': '314', \
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', \
'Cookie': 'YourCookie', \
'Host': 'fanyi.youdao.com', \
'Origin': 'http://fanyi.youdao.com', \
'Referer': 'http://fanyi.youdao.com/', \
'User-Agent': 'YourUserAgent', \
'X-Requested-With': 'XMLHttpRequest'
}
form_data = {}
# 需要翻译的文字
form_data['i'] = '德莉莎世界第一可爱'
# 下面这些都先按照我们之前抓包获取到的数据
form_data['from'] = 'AUTO'
form_data['to'] = 'AUTO'
form_data['smartresult'] = 'dict'
form_data['client'] = 'fanyideskweb'
form_data['salt'] = to_salt
form_data['sign'] = to_sign
form_data['ts'] = to_ts
form_data['bv'] = to_bv
form_data['doctype'] = 'json'
form_data['version'] = '2.1'
form_data['keyfrom'] = 'fanyi.web'
form_data['action'] = 'FY_BY_REALTlME'
同理找到它发回的数据结构
这时候其实已经可以发送需要翻译的请求了,但是会返回errorcode:50,因为有道对爬虫有一些限制,需要处理salt, sign, ts这几个数据。
回到网页,在它的Elements中找到一个看似跟翻译有关的js文件
把这个网址打开,复制里面所有的内容,百度JS HTML格式化,打开相关网址(http://www.bejson.com/jshtml_format/),将刚才复制的内容粘贴进去,点击格式化,把格式化之后的内容存到一个文档里,然后分析这些代码
搜索salt,然后一个个排查,这里我就将他最后加密的函数直接截图出来
navigator.appVersion 表示浏览器版本
这是java script语法,同样得把它转换成python代码(我只是想学个py,然后我为何去看js了?)
代码粘上
def getMd5(value):
import hashlib
md5 = hashlib.md5()
md5.update(bytes(value, encoding='Utf-8'))
md5_str = md5.hexdigest()
return md5_str
r = "" + str((time.time() * 1000))
i = r + str(random.randint(0,10))
to_salt = i
to_sign = getMd5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj")
to_ts = r
#谷歌浏览器某版本md5
to_bv = '6bd43b532a04b6145782cfe65196ca4f'
至此全流程清晰了,剩下的就是发包这种接口调用的事情了,粘上全部代码
import json
import requests
import time
import random
import hashlib
def getMd5(value):
import hashlib
md5 = hashlib.md5()
md5.update(bytes(value, encoding='Utf-8'))
md5_str = md5.hexdigest()
return md5_str
def get_translate_date(e):
url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
r = "" + str((time.time() * 1000))
i = r + str(random.randint(0,10))
to_salt = i
to_sign = getMd5("fanyideskweb" + e + i + "n%A-rKaT5fb[Gy?;N5@Tj")
to_ts = r
#谷歌浏览器某版本md5
to_bv = '6bd43b532a04b6145782cfe65196ca4f'
form_data = {}
# 需要翻译的文字
form_data['i'] = e
# 下面这些都先按照我们之前抓包获取到的数据
form_data['from'] = 'AUTO'
form_data['to'] = 'AUTO'
form_data['smartresult'] = 'dict'
form_data['client'] = 'fanyideskweb'
form_data['salt'] = to_salt
form_data['sign'] = to_sign
form_data['ts'] = to_ts
form_data['bv'] = to_bv
form_data['doctype'] = 'json'
form_data['version'] = '2.1'
form_data['keyfrom'] = 'fanyi.web'
form_data['action'] = 'FY_BY_REALTlME'
headers ={
'Accept': 'application/json, text/javascript, */*; q=0.01', \
'Accept-Encoding': 'gzip, deflate', \
'Accept-Language': 'en,zh-CN;q=0.9,zh;q=0.8', \
'Connection': 'keep-alive', \
'Content-Length': '238', \
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', \
'Cookie': 'OUTFOX_SEARCH_USER_ID=-1293870634@222.128.56.148; JSESSIONID=aaaQmWwIFXYcI45B_GW9w; OUTFOX_SEARCH_USER_ID_NCOO=859230941.8657871; ___rl__test__cookies=1578144246831', \
'Host': 'fanyi.youdao.com', \
'Origin': 'http://fanyi.youdao.com', \
'Referer': 'http://fanyi.youdao.com/', \
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36', \
'X-Requested-With': 'XMLHttpRequest'
}
#form_data = urllib.parse.urlencode(form_data).encode('utf-8')
response_data = requests.post(url = url,data = form_data,headers = headers)
# 把返回来的json字符串解析成字典
result_dict = json.loads(response_data.text)
#print(result_dict )
print('翻译:' + result_dict['translateResult'][0][0]['tgt']+ '\n')
if 'smartResult' in result_dict:
print('相关结果:')
size = len(result_dict['smartResult']['entries'])
if size > 1:
for x in range(1,len(result_dict['smartResult']['entries'])):
print(result_dict['smartResult']['entries'][x])
while(1):
in_str = input('请输入:')
get_translate_date(e = in_str)
测试结果:
尝试输入传统的 你好世界