Python - urllib2/urllib.request
urllib2/urllib.request
Python2.7: urllib2
Python3: urllib.request
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
构造一个请求对象.
url: 请求的有效URL.data: 请求的附加数据.- Python3.3 之前, 请求的方法根据
data判断.'GET' if data is None else 'POST' data的类型要对应headers中的Content-Type属性. 如果data不为空, 而且headers中又没有指定Content-Type, 则默认为application/x-www-form-urlencoded. 所以, 一般 HTTP POST 请求的数据要用urllib.parse.urlencode()(python2urllib.urlencode()) 来转换为application/x-www-form-urlencoded格式.
- Python3.3 之前, 请求的方法根据
headers: 请求的头部. 如{'Accept': 'text/html', 'Content-Type': 'multipart/form-data'}origin_req_hostunverifiablemethod: New in Python3.3, 请求的方法,如:HEAD,GET,POST. 在 Python3.3 之前,请求的方法由data决定'GET' if data is None else 'POST'.
urllib.request.urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, cafile=None, capath=None, cadefault=False, context=None)
Open the URL url, which can be either a string or a Request object.
url: 请求的 URL,或构造好的请求对象urllib.request.Request().data: 请求的附加数据,同urllib.request.Request()的data参数.timeout: 请求的超时时间, 默认为 socket 的默认超时时间_GLOBAL_DEFAULT_TIMEOUT.cafile,capath: HTTPS 请求的 CA 证书. 主要作为参数传给ssl.create_default_context()context: ssl.SSLContext 实例
正常返回一个 HTTP 请求, 返回对象有以下方法:
getcode(): HTTP 的响应状态码.geturl(): 当前返回内容的 URL,可以用来判断是否重定向.info(): HTTP 的响应头部信息.dict: 头部信息字典get(name): 获取头部信息中名为name的值, 相当于dict.get(name)getheader(name): 同get(name)
返回的body内容可以通过read()读取.
简单例子:1
2
3
4from urllib.request import Request, urlopen
request = Request('http://www.lizs.cc')
response = urlopen(Request, timeout=3)
注意, urlopen() 请求的返回对象如果不是 2xx 是会报错的. 如果想知道响应是否为 404 怎么办? 可以通过捕获 HTTP.Error 错误来获取.1
2
3
4
5
6
7
8
9
10from urllib.request import Request, urlopen, HTTPError
request = Request('http://www.lizs.cc')
try:
response = urlopen(Request, timeout=3)
except HTTPError, err_response:
response = err_response
print(response.getcode()) # 响应状态码
print(response.info()) # 响应的头部
print(response.read()) # 响应的内容(主体)
Handler 类
模块处理器类,用来创建 opener。
urllib.request.build_opener(*handlers)
创建 opener 对象.
-*handlers, 创建 opener 所需的Handler. 如: build_opener(handler), build_opener(handler1, handler2), build_opener(*[handler1, handler2])
创建 opener 的时候会自动加载以下默认 Handler:
ProxyHandler,UnknownHandler,HTTPHandler,HTTPDefaultErrorHandler,HTTPRedirectHandler,FTPHandler,FileHandler,HTTPErrorProcessor.如果提供的
*handler中, 有默认Handler的子类(issubclass), 创建 opener 的时候将去掉相应的默认 Handler.
urllib.request.install_opener(opener)
将 opener 设置为默认 opener.
模块的一般使用步骤:
- 确定 Handler。
- 创建、安装 opener。
- 使用
urlopen()完成请求。
不创建 opener 直接 urlopen() 会使用默认的 opener (使用默认 Handler)。
自定义 Handler 处理 HTTPError
模块默认 Handler 对 HTTP 响应状态码不是 200 <= code < 300的,都 raise HTTPError 来处理的,有时候很不方便,我们可以自定义一个Handler来处理 HTTPError。
默认 Handler 中,HTTPDefaultErrorHandler 会 raise 所有 HTTPError。1
2
3class HTTPDefaultErrorHandler(BaseHandler):
def http_error_default(self, req, fp, code, msg, hdrs):
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
重新定义处理 Handler:1
2
3class MyHTTPErrorHandler(urllib.request.HTTPDefaultErrorHandler):
def http_error_default(self, req, fp, code, msg, hdrs):
return urllib.request.HTTPError(req.get_full_url(), code, msg, hdrs, fp)
使用自定义的 Handler 来 urlopen:1
2
3
4opener = urllib.request.build_opener(MyHTTPErrorHandler)
urllib.request.install_opener(opener)
request = urllib.request.Request('http://www.lizs.cc')
response = urllib.request.urlopen(request, timeout=3)
因为,issubclass(MyHTTPErrorHandler, HTTPDefaultErrorHandler) == True,所以,HTTPDefaultErrorHandler 被去掉。
也可以通过定义 HTTPErrorProcessor 的子类来处理。因为,HTTPErrorProcessor 规定了响应状态码不为 200 <= code < 300 都是 HTTPError。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class HTTPErrorProcessor(BaseHandler):
"""Process HTTP error responses."""
handler_order = 1000 # after all other processing
def http_response(self, request, response):
code, msg, hdrs = response.code, response.msg, response.info()
# According to RFC 2616, "2xx" code indicates that the client's
# request was successfully received, understood, and accepted.
if not (200 <= code < 300):
response = self.parent.error(
'http', request, response, code, msg, hdrs)
return response
https_response = http_response
定义 Handler 将 404 响应状态码归类到正常状态。1
2
3
4
5
6
7
8
9
10
11
12class MyHTTPErrorProcessor(urllib.request.HTTPErrorProcessor):
def http_response(self, request, response):
code, msg, hdrs = response.code, response.msg, response.info()
# According to RFC 2616, "2xx" code indicates that the client's
# request was successfully received, understood, and accepted.
if not (200 <= code < 300 or code == 404):
response = self.parent.error(
'http', request, response, code, msg, hdrs)
return response
当 HTTP 响应状态码为 200 <= code < 300 or code == 404 都不会 raise HTTPError.1
2
3
4opener = urllib.request.build_opener(MyHTTPErrorProcessor)
urllib.request.install_opener(opener)
request = urllib.request.Request('http://www.lizs.cc/404')
response = urllib.request.urlopen(request)
HTTP Basic Authorization
模块提供了 HTTPBasicAuthHandler(password_mgr=None) 来处理 HTTP Basic 认证。
password_mgr: 密码管理器,可以用HTTPPasswordMgrWithDefaultRealm。
1 | uri = 'http://www.lizs.cc' # 需要 Basic 认证的url |