标签:http请求 出现 ftp debug response 默认 头部 爬虫 url参数
urllib库
简介
urllib是python内置的HTTP请求库。它包含以下4个模块:
通过urllib库来获取网页内容是一个福音。我们只需关心请求的链接是什么,需要传的参数是什么,如何设置可选的请求头即可,而无需深入到底层了解它到底是怎么传输和通信的。
使用
构造请求
使用urllib的request模块构造HTTP请求,实现请求的发送并获取响应。
1. urlopen()
urlopen的API:urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
url参数:
通过②③,我们知道了在urlopen()函数里传入一个URL,将返回一个HTTPResponse类型的对象。是对象就包含一些属性和方法,对吧?哈哈:
read()、readinto()、getheader(name)、getheaders()、fileno()等方法;msg、version、status、reason、debuglevel、closed等属性。
注意:getheaders()是复数形式,返回头部的全部信息;getheader(name)是单数的,表示按需获取。
对比:
库名 | urllib库 | requests库 |
---|---|---|
构造请求 | request.urlopen(url) | get(url) |
响应状态 | status | status_code |
响应内容 | read() | text |
加入Headers等信息 | 先行构建一个Request类型的对象,并使之作为request.urlopen()方法的参数 | 直接在get()方法中使用headers参数 |
如何理解使用urllib获取的响应体是使用read()方法来解析?姑且将其获得的响应体看作一个file-like对象,而对文件使用read()方法自然说得过去了。
data参数:如果传递了这个参数,则请求方式不再是GET方式,而是POST方式。该参数为bytes类型,需使用bytes()方法转化。
传递的参数出现在了form字段中,说明是表单提交。这是一个POST请求确证凿凿。
timeout参数:用于设置超时时间。若请求超出了设置的这个时间尚未获取响应,将抛出异常。不指定则会使用全局默认时间。
出现异常:
捕获异常:
其他参数:
cafile和capath分别指定CA证书和它的路径,在请求HTTPS链接是会有用。
cadefault参数现已弃用,其默认值为False。
context参数则必须为ssl.SSLContext类型,用来指定SSL设置。
2. Request
urlopen()方法可以实现最基本的请求的发起,但这个请求并不完整。如果请求中需要加入Headers等信息,就需要通过Request类来构建了。
通过构造Request数据结构,一方面可以将请求独立为一个对象,另一方面我们也可以更加灵活地配置参数。这颇有点囊括宇宙的意味。
Request的API:urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
除了第一个参数为必选的之外,其余均为可选参数。
上面是很教条化的东西。下面,让我们看两个例子吧。
第一个例子:
① 先导入urllib.request模块;
② 再通过向urllib.request模块中的Request类传入一个URL构建一个请求实例;
③ 之后,我们再将请求对象作为urlopen()方法的参数来获取服务器的响应;
④ 最后,打印出请求的内容。
整个流程分为:URL构建请求对象→ 传入请求对象获取响应 → 输出响应内容
第二个例子:
① 先导入urllib.request模块和urllib.parse模块;
② 确定url——使用赋值的方式,将url具体化。直接传入urlopen()也无碍,这里是为了防止api的书写过长;
③ 构建一个请求头(通过User-Agent可以模拟任何的浏览器,防止爬虫身份的暴露);
④ 构建一个字典存储表单的信息。由于该参数要求为字节流格式,我们还需要分两步走:
先将之序列化——使用urllib.parse模块的urlencode()方法,
再将之转换为字节流编码格式的内容——使用bytes()函数
⑤ 准备齐全就可以开始构建一个Request类的实例了。下面的例子将之赋值给request
⑥ 最后,将请求对象传入urllib.request模块的urlopen()方法,成功获取了服务器的响应并打印出响应内容。
3. 高级用法
上面我们所构建的请求,对于一些更为高级的操作(如登录认证,代理设置,Cookies处理等等)就显得无能为力了。为此,引入了Handler和Opener,以便深入一层进行配置(通过使用底层的实例来完成了)。
(1) Handler对应BaseHandler类(所有其他Handler的父类):
(处理器之意,正所谓“术业”chu li qi 有专攻:有处理登录验证的,有处理Cookies的,有处理代理设置的)。
(2) Operner对应OpenerDirector类:
Opener可以使用open()方法,返回类型和urlopen()一致。
PS:之前使用的Request和urlopen()方法,是一个默认的opener(相当类库为我们封装好了的常用的请求方法)。
(3) Opener与Handler的关系:使用Handler来构建Opener(实例化一个Opener, 然后再通过它调用一些handler实例)。
下面,来观望几个例子:
验证
from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener from urllib.error import URLError username = ‘username‘ password = ‘password‘ url = ‘http://localhost:5000/‘ p = HTTPPasswordMgrWithDefaultRealm() p.add_password(None, url, username, password) auth_handler = HTTPBasicAuthHandler(p) opener = build_opener(auth_handler) try: result = opener.open(url) html = result.read().decode(‘utf-8‘) print(html) except URLError as e: print(e.reason)
这个例子使用了一个add_password之后的HTTPPasswordMgrWithDefaultRealm对象,作为参数构造了一个HTTPBasicAuthHandler实例,即处理验证的Handler。接着将该Handler传给build_opener()方法构建一个Opener。一旦这个Opener发送请求,则代表验证成功。
代理
from urllib.request import ProxyHandler, build_opener from urllib.error import URLError proxy_handler = ProxyHandler({ ‘http‘: ‘http://127.0.0.1:5000‘, ‘https‘: ‘https://127.0.0.1:5000‘ }) opener = build_opener(proxy_handler) try: response = opener.open(‘https://www.baidu.com‘) print(response.read().decode(‘utf-8‘)) except URLError as e: print(e.reason)
Cookies
import http.cookiejar, urllib.request from urllib.error import URLError cookie = http.cookiejar.CookieJar() handler = urllib.request.HTTPCookieProcessor(cookie) opener = urllib.request.build_opener(handler) try: response = opener.open(‘http://www.baidu.com‘) except URLError as e: print(e.reason) for item in cookie: print(item.name + ‘=‘ + item.value)
处理异常
urllib.error模块定义了由request模块产生的异常。也就是说,若程序出现了问题,request模块会抛出error模块中定义的异常。
URLError类: 继承自OSError类,是error异常的基类。因此,由request模块产生的异常都可以通过这个类来处理。
(有一个属性)
HTTPError类: URLError类的子类,专门用于处理HTTP请求错误,比如认证失败等。
(有三个属性)
注意:有时,reason属性返回的不一定是字符串,也可能是一个对象。
import urllib.request import urllib.error import socket try: response = urllib.request.urlopen(‘https://www.baidu.com‘, timeout=0.01) except urllib.error.URLError as e: print(type(e.reason)) if isinstance(e.reason, socket.timeout): print(‘TIME OUT‘)
总结
以上的介绍,主要涉及到urllib库中的urllib.request和urllib.error模块。
urllib.request模块主要用于构造请求。使用urlopen()可以构造基本的请求,使用Request类构建更为完整的请求,使用Handler和Opener类可以构造更为高级的请求。
后两者与urlopen()的关系:
urllib.error模块主要用于处理urllib.request模块产生的异常。其中URLError类异常是HTTPError类的基类,在处理时应当先使用范围较小的异常类进行处理,再涵盖范围较大的。
本文参考:《Python3 网络爬虫开发实战》
标签:http请求 出现 ftp debug response 默认 头部 爬虫 url参数
原文地址:https://www.cnblogs.com/RajXie/p/9732408.html