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_host
unverifiable
method
: 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 |