2、使用urllib模块读取网络资源、发送请求参数、读取受保护的网络资源
1)打开URL对应的资源
- urlopen(url, data=None) 方法(urllib.request子模块下):用于打开 url 指定的资源,并从中读取数据
import urllib.request
with urllib.request.urlopen('http://www.crazyit.org/index.php') as f:
print(f.read(540).decode('UTF-8')) # 打开网络资源后,该资源可理解为一个文件
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>企业应用开发与实践 CrazyIt做最受欢迎的Java论坛</title>
<meta name="keywords" content="Java论坛,疯狂Java,Android,学习,论坛,Java知识论坛,前端开发,SpringMVC,SpringCloud,SpringBoot,Redis,Shiro,Hibernate,Spring,hadoop,云计算,大数据,AI,人工智能" />
2)发送请求参数
(1)模拟 test 的网站服务端:
- test/get.jsp 页面将收到的 name 和 password 数据返回
- test/post.jsp 页面将请求方式与受到的 name 和 password 数据返回
- test/put 返回“Got Data:put数据”
(2)urlopen() 函数:向被请求的 url 发送数据
- GET 请求直接将请求参数追加到 url 后面即可
params = {'name':'fkit', 'password':'6656565'}
with urllib.request.urlopen('http://192.168.1.17:8888/test/get.jsp?%s' & urllib.parse.urlencode(params)) as f:
print(f.read().decode('UTF-8'))
- POST 请求用 data 参数
params = {'name':'fkit', 'password':'6656565'}
with urllib.request.urlopen('http://192.168.1.17:8888/post.jsp', data=urllib.parse.urlencode(params).encode('UTF-8')) as f:
print(f.read().decode('UTF-8'))
- PUT、PATCH、DELETE 等请求需要使用 urllib.request.Reques 来构建请求参数,构建 Request对 象时,可通过 method 参数指定请求方式
# put请求参数
params = 'put数据'.encode('UTF-8')
# 创建Request对象
req = urllib.request.Request(url='http://192.168.1.17:8888/test/put', data=params, method='PUT')
with urllib.request.urlopen(req) as f:
print(f.read().decode('UTF-8'))
3)访问受保护的资源
(1)模拟 test 的网站服务端
- test/secret.jsp 页面为受保护的资源,需要登录(test/login.jsp)后才能访问
(2)http.cookiejar 模块:可管理 session id
- 访问受保护的资源时:
import urllib.request
with urllib.request.urlopen('http://192.168.1.17:8888/test/secret.jsp') as f:
print(f.read().decode('UTF-8'))
分析:访问被保护的资源时必须先登录才能访问
- 登录访问受保护的资源:
import urllib.request
params = {'name':'crazyit.org', 'pass':'leegang'}
# 登录
with urllib.request.urlopen('http://192.168.1.17:8888/test/login.jsp', data=urllib.parse.urlencode(params).encode('UTF-8')) as f:
print(f.read().decode('UTF-8'))
with urllib.request.urlopen('http://192.168.1.17:8888/test/secret.jsp') as f:
print(f.read().decode('UTF-8'))
分析:
- Web 应用基于 HTTP 协议通信,HTTP 是一种不保存状态,即无状态(stateless)协议
- 实际中,网站的登录基于 cookie
- 保持登录状态访问受保护的资源:
- python 中 http.cookiejar 模块可管理 session id
- 登录后用 cookie 记录登录后的 session id,下次使用同样的 session id 登陆即可读取受保护的资源
import urllib.request
import http.cookiejar
# 创建 Cookiejar 对象
cookie_jar = http.cookiejar.MozillaCookieJar('a.txt')
# 创建 Cookie 处理器
cookie_proc = urllib.request.HTTPCookieProcessor(cookie_jar)
# 创建 OpeneDirector 对象(当程序使用 OpeneDirector 对象发送多次请求时,它们使用相同的Cookie,因此服务端就可以维持多次访问状态)
opener = urllib.request.build_opener(cookie_proc)
params = {'name':'crazyit.org', 'pass':'leegang'}
# 登录,使用 opener 的 open() 方法
with opener.open('http://192.168.1.17:8888/test/login.jsp', data=urllib.parse.urlencode(params).encode('UTF-8')) as f:
print(f.read().decode('UTF-8'))
# 使用 opener 的open()方法(可多次 open 与服务器建立请求,服务器可根据 Cookie 来维护它们的状态)
with opener.open('http://192.168.1.17:8888/test/secret.jsp') as f:
print(f.read().decode('UTF-8'))