Python爬虫之urllib+Json+post向有道翻译发送数据获得翻译结果
这篇文章要介绍的内容是,使用urllib和Json库,通过post向浏览器发送数据,从而实现利用Python就可以使用爬虫网站的特定功能:我们这篇的实例是向《有道翻译》中发送数据,并自动给出翻译。如下图1所示:
图1
首先我们还是先给出代码:
from urllib import request#注释1
from urllib import parse
import json
def get_translate_data(word=None):#注释2
url = 'http://fanyi.youdao.com/translate'
Form_data = {'i': word,#注释3
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': '15449700474491',
'sign': '8fdb2ff5ee4404b5cbfc6ab680c4c3a9',
'ts': '1544970047449',
'bv': '43e33a3a925d7379c362f3cbcb58032f',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTIME',
'typoResult': 'false'
}
data = parse.urlencode(Form_data).encode('utf-8')
response = request.urlopen(url, data)
html = response.read().decode('utf-8')
#将Json格式字符串转成字典
content = json.loads(html)
#打印翻译后的数据
print(content['translateResult'][0][0]['tgt'])
if __name__ == '__main__':
tanslate = input("请输入要翻译的内容:")
get_translate_data(tanslate)
输出结果如图2所示:
图2
再给出代码解释之前呢,我们先来知道一些内容:
1、 get和post请求:
——所谓的get方法,便是利用程序使用HTTP协议中的GET请求方式对目标网站发起请求,同样的还有POST,PUT等请求方式,其中GET是我们最常用的,通过这个方法我们可以了解到一个请求发起到接收响应的过程。(HTTP常见请求方式:http://www.runoob.com/http/http-methods.html)
——post请求方式的使用和get方式并没有很大的区别,本质的区别在于它传递参数的方式并不像get方式一样,通过在url中拼接字段来发送给服务器,他采取了一种相较之下更为安全的操作方式,通过form表单的方式来向服务器传递查询条件。我们同样可以通过浏览器的F12开发者工具或者fiddler抓包工具来看到formdata这个字段,从中获取form表单中的字段信息,很多登录操作就是基于此。post除了构造表单以外还可以像通过向服务器发送json信息的方式获取正确的请求,利用的便是中post(json={“key”:“value”})的方式,操作流程大致与post发送form表单相似,这个例子呢我们使用的就是post第二种方式——通过json方式向服务器发送数据。
当然更多内容可以参考这篇文章:https://www.imooc.com/article/48845?block_id=tuijian_wz
2、 如何知道我们的网站翻译功能是post请求呢?
当然还是要通过开发者模式中去审查页面的元素。手动过程如下:
F12>Network>XHR>Headers>General中可以看到,它的RequestMethod是post方法如图3所示。
图3
那接下来正式开始代码的讲解:
1、 注释1——Urllib库
Urllib是python内置的HTTP请求库
包括以下模块
- urllib.request 请求模块
- urllib.error 异常处理模块
- urllib.parse url解析模块
- urllib.robotparser robots.txt解析模块
这次用到的是urllib.request请求模块和urllib.prase url解析模块所以我们针对这些内容重点讲解一下:
urllib.request这个模块用得比较多, 尤其是urlopen函数,会返回一个二进制的对象,对这个对象进行read()操作可以得到一个包含网页的二进制字符串,然后用decode()解码成一段html代码:
语法结构:
urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None, capath=None, cadefault=False, context=None)
参数:其中url既可以是一个URL字符串,又可以是一个Requst对象,一般使用后者添加其他参数。当request的方式是post时,使用参数data,用于填写传递的表单信息,将data填好表单信息,准备传入urlopen 前,还需要利用urllib.parse里的urlencode()函数转换格式,写成data = urllib.parse.urlencode(data).encode(‘’),然后将data传入函数。
而urllib.request的Request函数,也可以用于打开url字符串,同时可以传入更多的参数,例如:headers,Request函数可以返回一个request对象作为urlopen函数的url参数使用。
语法结构:
urllib.request. Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
参数:其中url是一个URL字符串。
data用法与urlopen一致。
headers参数是一个字典,服务器对于用户发出的request,会通过其中的headers信息来判断用户发信息,我们可以通过自己编写headers传入urllib.request. Request中用于伪装自己的身份。Header中User-agent参数是判断用户身份。另外通过设置代理可以改变用户提交时的IP地址。
以上内容参考博客:https://www.cnblogs.com/fu-yong/p/9016819.html
2、 注释2——传参函数
在这里定义一个传参函数get_translate_data(word=None),可以在主函数中通过函数调用、传递参数然后得到想要的结果。
3、 注释3——Form-Data
可以使用data参数,向服务器发送数据,而这个data数据可以不用自己去定义直接拿来用即可:F12>Network>XHR>Headers>Form Data如图4所示:
图4
将这些数据复制出来,并生成字典,生成的字典如下,并将键”i”对应的值改为word,这样我们就可以实现通过函数传递参数。
Form_data = {'i': '我爱中国',
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': '15449700474491',
'sign': '8fdb2ff5ee4404b5cbfc6ab680c4c3a9',
'ts': '1544970047449',
'bv': '43e33a3a925d7379c362f3cbcb58032f',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTIME',
'typoResult': 'false'
}
4、 注释4——json.load()
将json字符串转化为字典,以便接下来使用。
5、 注释5——content[‘translateResult’][0][0][‘tgt’]
看到这个代码不要急,还是回到页面,如图5,摁下F12打开开发者模式,依次F12>Network>XHR>Headers>Preview
图5
通过这个可以准确的看到,translateResult这个在外层是两层的列表,最内层是字典,这样就不难明白当引用翻译结果的时候应该是content[‘translateResult’][0][0][‘tgt’]一层层的去读取到指定内容。
6、 注释6——主函数
这个本不应该是一个问题,因为刚开始比较马虎,写完程序后,出现以下报错。后来反复检查,最后发现有人也犯了同样的错误如图8,这才发现name两端可是双下划线的,并不是只有一个。
Unresolved reference '_name_' less... (Ctrl+F1) Inspection info: This inspection detects names that should resolve but don't. Due to dynamic dispatch and duck typing, this is possible in a limited but useful number of cases. Top-level and class-level items are supported better than instance items,
图6
7、 问题
刚开始调用有道翻译api接口时,写的URL是url=’http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule’出现了问题
百度了一下终于找到了问题所在,有道翻译的接口不是:
http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
而是:http://fanyi.youdao.com/translate,这样显示的正确结果如图6。
总结:
这篇文章使用urllib和Json库,通过post向浏览器发送数据,从而实现利用Python就可以使用爬虫网站的特定功能,通过一个实例简单的介绍了一下post请求数据的应用,内容较为不算太难,也容易上手。当然实现这个功能的代码还有很多,我们还可以使用requests和json库实现,代码如下
import requests
import json
def get_translate_data(word=None):
url = 'http://fanyi.youdao.com/translate'
Form_data = {'i': word,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': '15449700474491',
'sign': '8fdb2ff5ee4404b5cbfc6ab680c4c3a9',
'ts': '1544970047449',
'bv': '43e33a3a925d7379c362f3cbcb58032f',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTIME',
'typoResult': 'false'
}
response = requests.post(url,data = Form_data)
#将Json格式字符串转成字典
content = json.loads(response.text)
#打印翻译后的数据
print(content['translateResult'][0][0]['tgt'])
if __name__ == '__main__':
tanslate = input("请输入要翻译的内容:")
get_translate_data(tanslate)
这个代码相对上面那个,是更容易理解的。所以更建议使用下面这个。好了,这篇文章的内容就到这了,欢迎大佬们批评指正。