今天在做有道翻译爬虫练习,发现服务器一直返回 {"errorCode":50} 这个错误,后来发现原来有道添加了反爬机制的验证 salt 和 sign。
经过查看页面源码中发现一个 fanyi.min.js 文件,如图:
打开这个 js 文件, 复制JS中内容用http://tool.oschina.net/codeformat/js 格式化后 ,在内容中搜索 salt 会搜出 3 处结果:
结果一:
结果二:
结果三:
这个三个结果到底是看哪一个呢? 通过使用 fiddler 抓取的包发现,version: 2.1,所以直接看搜索结果三中的代码:
然后分析搜索结果中的代码:
OK,找到这些后,我们照着代码样子,用python的方式,生成一个时间戳 和 sign 即可。
全部代码如下:
# -*- coding:utf-8 -*-
'''
使用 POST 方式抓取 有道翻译
urllib2.Request(requestURL, data=data, headers=headerData)
Request 方法中的 data 参数不为空,则默认是 POST 请求方式
如果 data 为空则是 Get 请求方式
{"errorCode":50}错误:
有道翻译做了一个反爬虫机制,就是在参数中添加了 salt 和 sign 验证,具体操作说明参考:
http://www.tendcode.com/article/youdao-spider/
'''
import urllib, urllib2
import time
import random
import hashlib
import sys
# 字符串转 utf-8 需要重新设置系统的编码格式
reload(sys)
sys.setdefaultencoding('utf8')
# 目标语言
targetLanguage = 'Auto'
# 源语言
sourceLanguage = 'Auto'
headerData = {
'Cookie': '[email protected];',
'Referer': 'fanyi.youdao.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
# 语言类型缩写
languageTypeSacronym = {
'1': 'zh-CHS 》 en',
'2': 'zh-CHS 》 ru',
'3': 'en 》 zh-CHS',
'4': 'ru 》 zh-CHS',
}
# 翻译类型
translateTypes = [
'中文 》 英语',
'中文 》 俄语',
'英语 》 中文',
'俄语 》 中文'
]
def startRequest(tanslateWd):
requestURL = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
client = 'fanyideskweb'
timeStamp = getTime()
key = 'ebSeFb%=XZ%T[KZ)c(sy!'
sign = getSign(client, tanslateWd, timeStamp, key)
data = {
'i': tanslateWd,
'from':sourceLanguage,
'to':targetLanguage,
'client':client,
'doctype':'json',
'version':'2.1',
'salt':timeStamp,
'sign':sign,
'keyfrom':'fanyi.web',
'action':'FY_BY_REALTIME',
'typoResult':'true',
'smartresult':'dict'
}
data = urllib.urlencode(data)
request = urllib2.Request(requestURL, data=data, headers=headerData)
resonse = urllib2.urlopen(request)
print(resonse.read())
# 生成时间戳
def getTime():
return str(int(time.time() * 1000) + random.randint(0, 10))
# 生成 Sign
def getSign(client, tanslateWd, time, key):
s = client + tanslateWd + time + key
m = hashlib.md5()
m.update(s.encode('utf-8'))
return m.hexdigest()
def getTranslateType(translateType):
global sourceLanguage, targetLanguage
try:
if translateType:
l = languageTypeSacronym[translateType].split(' 》 ')
sourceLanguage = l[0]
targetLanguage = l[1]
except:
print('翻译类型选择有误,程序将使用 Auto 模式为您翻译')
if __name__ == '__main__':
print('翻译类型:')
for i, data in enumerate(translateTypes):
print('%d: %s' %(i + 1, data))
translateType = raw_input('请选择翻译类型:')
getTranslateType(translateType)
tanslateWd = raw_input('请输入要翻译的消息:')
startRequest(tanslateWd)