python的urllib可谓http操作的神器,可以模仿浏览器的行为提交请求并收到返回的数据。笔者在此利用urllib向百度翻译发送翻译请求并获取翻译结果,演示一下该库的简单用法,小脚本封装后可以在命令行下运行,非常适用于linux。
功能分析
- 输入中文或英文,返回翻译结果。
代码实现
- urllib发送请求的方法
#!/usr/bin/env python3
from urllib import request, parse
import json
import sys
# 新建请求
requ = request.Request('http://...') # 输入请求的目标网址
# 以post方式提交数据需要对数据转码打包
post_data = parse.urlencode({
"key": "val",
# ...
})
# 添加请求头request-header
requ.add_header(key, val) # 请求头可以从浏览器控制台获取,可以多次调用
# 发送请求获取响应数据
with request.urlopen(requ, post_data.encode('utf-8')) as resp
resp_data = resp.read() # 字节数据,可根据需要解码为字符
以上就是urllib发送请求并获取相应数据的一般方法,下面根据上面的模板向百度翻译发送翻译请求。
- 翻译小程序
#!/usr/bin/env python3
from urllib import request, parse
import json
import sys
def show_help():
print('help...')
def main():
if len(sys.argv) < 2:
show_help()
return
words = sys.argv[1]
# post数据结构,query为待查询词汇
post_data = parse.urlencode({
"from":"zh",
"to":"en",
"query":words,
# "query":"键盘",
"transtype":"translang",
"simple_means_flag":"3"
})
requ = request.Request('http://fanyi.baidu.com/v2transapi')
requ.add_header('Host', 'fanyi.baidu.com')
requ.add_header('User-Agent', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) \
Gecko/20100101 Firefox/50.0')
requ.add_header('Accept', '*/*')
requ.add_header('Accept-Language', 'en-US,en;q=0.5')
requ.add_header('Accept-Encoding', 'en-US,en;q=0.5')
requ.add_header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
requ.add_header('X-Requested-With', 'XMLHttpRequest')
requ.add_header('Referer', r'http://fanyi.baidu.com/translate?aldtype=16047&query=\
%E5%B8%AE%E5%8A%A9&keyfrom=baidu&smartresult=dict&lang=auto2zh')
requ.add_header('Content-Length', '78')
requ.add_header('Cookie', r'BAIDUID=F49EF7F92D1F9D27EBC7CFB34A5EB604:FG=1; BIDUPSID\
=EB895CEBA4E3BAD19DC355A2ED379DED; PSTM=1481521457; H_PS_PSSID=21764_1456_21085\
_17001_21554_20928; PSINO=1; locale=zh; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574\
=1481991435,1481991979; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1481991979; MA\
NUBANNER=1; from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E\
2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D\
%5D; to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%\
22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; REAL\
TIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; sideAdClose=17152')
requ.add_header('Connection', 'keep-alive')
resp = request.urlopen(requ, post_data.encode('utf-8'))
print(json.loads(resp.read().decode('utf-8')).get('liju_result').get('tag'))
if __name__ == "__main__":
main()
此处请求头来源于谷歌浏览器的控制台,并不是所有的都是必须的,读者可自行测试,另外,也可以写一个函数来直接对请求头文本进行自动分割,不需要手动分割。
附录
1. 请求头获取方法
从菜单打开开发者工具(或者直接F12打开)
打开Network选项
尝试翻译,查看请求头和数据格式
查看响应数据格式
利用json模块可以解析json数据。
2. 请求头文本自动分割方法
def parse_to_array(data_text):
"""Parse header text to tuple array."""
lines = data_text.splitlines()
data_array = []
for l in lines:
data_array.append(tuple(l.split(':',1)))
return data_array
def add_request_headers(reqs, headers):
"""Add request header according of headers text."""
dict_data = parse_to_array(headers)
for k, v in dict_data:
reqs.add_header(k, v)
# 用法展示
headers = """
Accept: */*
...
"""
add_request_headers(reqs, headers)
总结
利用该方法可以满足一般的爬取需求,笔者还实现过校园网wifi网页认证的便捷登陆以及校园网流量监控系统,后者还需要结合邮件发送模块实现定期自动发送邮件提醒,有时间写出来交流交流。