python爬虫学习之路(2) 利用urllib爬取有道翻译的结果

上一节学习了如何简单的获取一个网站的html代码,这次学习一下如何爬取一个网站返回的数据.比如:爬取有道翻译所翻译的结果.
在我们爬取有道翻译的结果前,我们需要将我们所要翻译的中文传到有道翻译的服务端,如何传送呢?这就需要用到 urlopen的data参数 .

urlopen的data参数



我们可以使用data参数,向服务器发送数据。根据HTTP规范,GET用于信息获取,POST是向服务器提交数据的一种请求,再换句话说:
从客户端向服务器提交数据使用POST;
从服务器获得数据到客户端使用GET(GET也可以提交,暂不考虑)。
如果没有设置urlopen()函数的data参数,HTTP请求采用GET方式,也就是我们从服务器获取信息,如果我们设置data参数,HTTP请求采用POST方式,也就是我们向服务器传递数据。
data参数有自己的格式,它是一个基于application/x-www.form-urlencoded的格式,具体格式我们不用了解, 因为我们可以使用urllib.parse.urlencode()函数将字符串自动转换成上面所说的格式。


下面让我们来尝试爬取一下有道翻译的网站:

1,首先打开有道翻译的网站:http://fanyi.youdao.com/
这里写图片描述
2, 打开调试页面:
这里写图片描述
3, 点击”Network”
这里写图片描述
4, 输入要翻译的中文,’你好世界’
这里写图片描述
可以看到调试栏多了一行东西,点击它.
5, 查看网站返回的结果

这里写图片描述

6, 查看它所传送的信息

这里写图片描述

从General中,我们可以找到有道翻译获取翻译结果的网址,所以我们需要访问这个网址,并获取翻译结果.上面已经说过了,我们不可以直接访问这个网址,还需要用data传送一些信息给有道翻译,让它知道我们要翻译的中文,现在我们需要知道有道翻译传到后台的data有什么内容.
7, 查看data
把刚才打开的’Headers’拉倒最后,就可以看见data里的内容:
这里写图片描述

8,编写一个爬虫


from urllib import request
from urllib import parse
import json
if name == “main“:
# 要访问的网站url
url = “http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
# 翻译的内容
translate = “你好世界”
# 将刚才网站获取的data存储在字典中
data = {}
data[“i”] = translate
data[“from”] = “AUTO”
data[“to”] = “AUTO”
data[“smartresult”] = “dict”
data[“client”] = “fanyideskweb”
data[“doctype”] = “json”
data[“version”] = “2.1”
data[“keyfrom”] = “fanyi.web”
data[“action”] = “FY_BY_REALTIME”
data[“typoResult”] = “false”
data[“salt”] = “1531479170173”
data[“sign”] = “41d6c46c8129965e4955dc9bff287de8”
# data参数有自己的格式,所以要将data使用urlencode方法转换标准格式
data = parse.urlencode(data).encode(‘utf-8’)
req = request.Request(url=url, data=data)
# 访问网站
response = request.urlopen(req)
# 获取结果
html = response.read().decode(“utf-8”)
# 将字符类型的html转换为字典
results = json.loads(html)
# 输出结果
print(results)


我们可以看一下返回来的结果
这里写图片描述
我们可以看到返回来的结果是一个字典,但不是我们所需要的字典,这是为什么呢?
这是因为有道翻译有着反爬机制,它会对data里的一些值进行加密,所以我们用与刚才相同的data是不可以爬取的,那么我们要怎么破解有道翻译的反爬机制呢?

破解有道翻译的反爬机制

1, 找到data中哪些数据是变化的,被加密的.
我们现在看看进行第二次翻译时data数据:
这里写图片描述
与上一次所获取的data的数据进行比较,我们可以看出,其实只有’salt’和’sign’两个属性的值发送了改变,其他并没有改变.那么现在我们需要找到这两个数据是如何来的.
2, 查找salt和sign是如何变化的
salt和sign会变化的可能性有两种:一种是:有道翻译在翻译中文前,先向服务器发送一个请求,并从服务器获取这两个值.一种是:利用js在本地生成.那么是哪种方法呢?我们来看看是哪种可能:
第一种可能需要向服务器发送请求,并返回两个值.所以我们要在’Network’中找到其他从服务器返回的内容,看看在其他请求中有没有这两个值:
这里写图片描述
我们查看五条数据,可以看出除了最后一个的内容不为空之外,其他都为空,所以可以判断不是第一种可能.
那么就是第二种可能咯,现在我们来找一下js是如何生成这两个数据的.
3, 找到js文件
这里写图片描述
复制这个网址,在其他标签打开.我们可以看到一个js文件,把这个文件的内容复制下来,打开站长工具:http://tool.chinaz.com/Tools/jsformat.aspx。把代码复制进去后,点击格式化,得到一个js文件:
这里写图片描述
把格式化后的代码复制到一个文本文档中.
4, 查找salt和sign的生成方法
在文档内查找’salt’,找到js是如何生成两个值:
这里写图片描述
我们可以看见salt的值是时间戳加上10以内的随机数,而sign则是字符串”’fanyideskweb’+要翻译的内容+salt+”ebSeFb%=XZ%T[KZ)c(sy!”进行md5加密后的值.
5, 重新写一个爬虫
还有在发送请求的时候,还要加上headers,headers的内如下:
这里写图片描述
但是,其实并不需要把所有内容都加到headers中,一般只需要:”User-Agent”,”Referer”,”Cookie”,这三个值就行了


from urllib import request
from urllib import parse
import json
import time
import random
from hashlib import md5

md5加密
def turn_md5(data):
md5_obj = md5()
md5_obj.update(data.encode(“utf-8”))
return md5_obj.hexdigest()

if name == ‘main‘:
# 要访问的网站url
url = “http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
# 翻译的内容
translate = ‘你好世界’
”’
获取salt和sign的值
salt 为当前时间的时间戳加上0-10的随机字符串
sign 为 四个字符串的加起来的md5的值
”’
salt = str(int(time.time()*1000) + random.randint(1, 10))
sign = turn_md5(“fanyideskweb” + translate + salt + “ebSeFb%=XZ%T[KZ)c(sy!”)
# 将刚才网站获取的data存储在字典中
data = {}
data[“i”] = translate
data[“from”] = “AUTO”
data[“to”] = “AUTO”
data[“smartresult”] = “dict”
data[“client”] = “fanyideskweb”
data[“doctype”] = “json”
data[“version”] = “2.1”
data[“keyfrom”] = “fanyi.web”
data[“action”] = “FY_BY_REALTIME”
data[“typoResult”] = “false”
data[“salt”] = salt
data[“sign”] = sign
# data参数有自己的格式,所以要将data使用urlencode方法转换标准格式
data = parse.urlencode(data).encode(‘utf-8’)
#
headers = {}
headers[“User-Agent”] = “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36”
headers[“Referer”] = “http://fanyi.youdao.com/
headers[“Cookie”] = “OUTFOX_SEARCH_USER_ID=-948455480@10.169.0.83; ” \
“JSESSIONID=aaajvZPcjhFWbgtIBPuiw; ” \
“OUTFOX_SEARCH_USER_ID_NCOO=1148682548.6241577;” \
” fanyi-ad-id=41685; fanyi-ad-closed=1; ___rl__test__cookies=” + salt
req = request.Request(url=url, data=data, headers=headers)
# 访问网站
response = request.urlopen(req)
# 获取结果
html = response.read().decode(“utf-8”)
# 将字符类型的html转换为字典
results = json.loads(html)
print(results[“translateResult”][0][0][“tgt”])


现在我们终于成功的获取到有道翻译的返回结果:
这里写图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值