爬取的网站http://fanyi.youdao.com/
遵循业内规则,我们先看一下robots协议http://fanyi.youdao.com/robots.txt
内容是这样的
OK,可以爬取,那我们就正式开始
我们爬虫的第一步自然是先要分析网页,我们先随便输入两个单词
可以看到,我们在输入内容后,右侧自动出现了翻译结果,这种情况一般是ajax异步加载
这里介绍一下什么是ajax异步加载
AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
摘自https://www.w3school.com.cn/ajax/ajax_intro.asp
打开抓包工具,输入单词来抓取网络请求
输入几个单词,果然得到了结果
打开请求,发现翻译结果
看一下请求头,市一个post方法,请求的url是http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
再来看下请求的表单,发现了一些复杂的参数,其中i,salt,sign,ts,bv看起来是有问题的
对比其他的请求,发现i:是输入的词,salt,sign,ts不知道是什么,其他的都是固定值
问题来了,salt,sign,ts是哪来的?
我们在google浏览器的开发者调试工具(F12)中搜索salt,看下有没有结果
搜索结果在一个js文件中,我们打开这个文件看一看
这js代码很明显不是给人看的,但是我们可以按下左下角的**{}将js代码格式化
格式化的代码如下
接下来让我们Ctrl+F**搜索一下我们想要的内容
一个一个往后找,看到了这个
很明显,salt是由一个名为i的函数生成了
我们按下上一个搜索结果的箭头,看见这样的代码片段
ts是现在的时间戳的字符串,i是r的后面加上一个随机数乘以10的结果,sign是一个md5结果
注意:js中的时间戳是一个整数,Python中的时间戳是一个浮点数
我们看一下sign的参数:
函数参数e是我们输入的词,而sign的参数是两个字符串加上我们输入的词加上i的值
知道了原理,现在开始写代码
md5
先说一下Python中md5的生成
在Python中md5生成需要使用hashlib库的md5
用法:
from hashlib import md5 #导入md5模块
result=md5("String".encode()).hexdigest() #获取md5结果
print(result) #输出结果
运行结果
27118326006d3829667a400ad23d5d98
我们用md5函数来生成一个md5对象,其中他的参数是一个二进制数据,在通过hexdigest方法转为md5字符串
时间戳的处理
我们在js中获得的时间戳有13位,而Python中获取的时间戳有17位,所以我们要将Python的时间戳乘以1000再转换成整型
import time
print(int(time.time()*1000))
数据提取
我们来看下返回的json数据
翻译结果是在translateResult中列表第一项的第一项的tgt中,即
[translateResult][0][0][tgt]
接下来开始写代码
我们先导入一些基本的模块,并创建一个Youdao类,定义一下它的初始化方法
import requests
import time
import random
from hashlib import md5
class Youdao():
def __init__(self):
self.word = input("输入你要翻译的内容>>>")
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36',
'Referer': 'http://fanyi.youdao.com/',
'Cookie': '[email protected]; OUTFOX_SEARCH_USER_ID_NCOO=1469412342.8594604; _ntes_nnid=069631a09195b5119a8e93159593722d,1585795354321; JSESSIONID=aaafrdxrCaUM1hKbBZFhx; ___rl__test__cookies=1588599225405',
}
self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
接下来让我们写一个方法来获得参数,返回请求表单
def get_data(self):
ts = int(time.time() * 1000)
salt = str(ts) + str(random.randint(0, 10))
sign = md5(('fanyideskweb' + self.word + salt + 'Nw(nmmbP%A-r6U3EUn]Aj').encode()).hexdigest()
return {
'i': self.word,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': salt,
'sign': sign,
'ts': ts,
'bv': '54005c0ddc47d3a4f8a58b098803c921',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME',
}
其中参数的生成方法我已经讲了,可参照上方代码实现部分
最后定义一个请求方法,返回并提取翻译结果
def translation(self):
data=self.get_data()
r=requests.post(self.url,headers=self.headers,data=data).json()
result=r['translateResult'][0][0]['tgt']
return result
完整代码如下
import requests
import time
import random
from hashlib import md5
class Youdao():
def __init__(self):
self.word = input("输入你要翻译的内容>>>")
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36',
'Referer': 'http://fanyi.youdao.com/',
'Cookie': '[email protected]; OUTFOX_SEARCH_USER_ID_NCOO=1469412342.8594604; _ntes_nnid=069631a09195b5119a8e93159593722d,1585795354321; JSESSIONID=aaafrdxrCaUM1hKbBZFhx; ___rl__test__cookies=1588599225405',
}
self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
def get_data(self):
ts = int(time.time() * 1000)
salt = str(ts) + str(random.randint(0, 10))
sign = md5(('fanyideskweb' + self.word + salt + 'Nw(nmmbP%A-r6U3EUn]Aj').encode()).hexdigest()
return {
'i': self.word,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': salt,
'sign': sign,
'ts': ts,
'bv': '54005c0ddc47d3a4f8a58b098803c921',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME',
}
def translation(self):
data=self.get_data()
r=requests.post(self.url,headers=self.headers,data=data).json()
result=r['translateResult'][0][0]['tgt']
return result
youdao=Youdao()
result=youdao.translation()
print(result)
原创不易,求支持