在Python3中,urllib和urllib2两个库合并为一个库,统一为urllib库。
urllib库是Python内置的HTTP请求库,主要包含如下4个模块:
- request:最基本的、也是最主要的HTTP请求模块,用来模拟发送请求。
- error:异常处理模块。
- parse:一个工具模块,提供了URL诸多处理方法,拆分、解析、合并等。
- robotparser:用来识别网站robot.txt文件,判断网站可不可以爬
1.request模块:发送请求
request模块,可以实现请求的发送并得到响应。主要有以下几个方法:
1.urlopen()
利用基本的urlopen()方法,可以完成最基本的网页GET请求。举个例子,以百度为例:
import urllib.request
response=urllib.request.urlopen("http://www.baid.com")
print(response.read().decode("utf-8"))
运行以上一段代码得到以下结果:
那么,我们获取到的response变量究竟是什么呢,打印一下他的类型可以看到是一个”<class 'http.client.HTTPResponse'>”类的对象,主要属性有msg,version,status,reason等,主要方法有read(), readinto(),getheader(name),getheaders()等。得到这个对象我们就可以调用这些方法和属性了。
比如在上面百度网站例子中说我们分别调用其中几个方法实例如下:
如果想给链接传递一些参数怎么操作呢,首先看文档中对urlopen()函数的解释:
*urllib.request.urlopen(url, data=None, timeout=<object object at 0x000000000049D760>, , cafile=None, capath=None, cadefault=False, context=None)
可以看到,除了url还有其他几个参数。一一介绍。
- data参数
可选参数,但是如果要添加该参数,需要通过bytes()方法转化为字节流格式的内容。添加这个参数请求方式由GET变为POST。比如,data=bytes(urllib.parse.urlencode({'world':'hello'}),encoding='utf-8')
- timeout参数
设置超时时间,比如设置timeout=1,如果请求超出此时间没有得到响应,则抛出异常。
2.Request()
urlopen()是request最基本的一个库,可以获取最简单的内容,但是复杂一点请求就无能为力了,比如加上headers内容,我们需要用更强大的Request方法构建。先看下Request的用法:
import urllib.request
request = urllib.request.Request("https://www.baidu.com")
response = urllib.request.urlopen(request)
print(response.read().decode("utf-8"))
上面代码中,虽然同样用的是urlopen方法发送请求,但是参数不再是URL,而是一个request的类的对象。使用Request我们可以更灵活更方便的在其中配置参数。
先看下Request类的API接口:
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
- url:必选参数,请求URL
- data:bytes字节流类型
- headers:字典,一般用来伪装成浏览器,若无此参数,服务器会识别到你是用Python访问,会判断你是爬虫拉黑,反爬虫的一种
- origin_req_host:请求方的host或IP
- unverifiable:表示这个请求是否是无法验证的,默认False。意思是用户有没有权限来接受请求内容。
- method:请求使用方法,比如GET,POST,PUT等
2.error模块:处理异常
urllib中的error模块定义了由request模块产生的异常,如果异常,request模块会抛出响应异常。
1.URLError
来自urllib的error模块,继承自OSError类,error异常模块基类,由request模块触发的异常都可以由此处理。有一个属性reason,即错误原因。
2.HTTPError
URLError的子类,专门处理HTTP请求错误,比如请求失败,它有3个属性:
- code:返回HTTP状态码,比如常见的404表示页面不存在
- reason:返回错误原因
- headers:返回请求头
下面是一个比较常见处理异常的代码写法:
from urllib import request, error
try:
respons = request.urlopen("www.aaaa.com")
except error.HTTPError as e:
print(e.reason, e.code, e.headers)
except error.HTTPError as e:
print(e.reason)
else:
print("Request Successfully")
因为HTTPError是URLError的子类,这样就可以先捕获HTTPError,获取他的状态信息,如果不是,则再去捕获URLError错误,输出原因。最后,用else来处理正常逻辑。
3.parse模块:解析链接
parse模块定义了URL的标准接口,实现URL各部分的抽取、合并以及链接转换。
1.urlparse()
先看一个例子,运行以下代码:
from urllib.parse import urlparse
result = urlparse("https://voice.baidu.com/act/newpneumonia/newpneumonia/?from=osari_pc_1")
print(type(result),"\n", result)
达到以下结果:
<class 'urllib.parse.ParseResult'>
ParseResult(scheme='https', netloc='voice.baidu.com', path='/act/newpneumonia/newpneumonia/', params='', query='from=osari_pc_1', fragment='')
可以看出,返回结果是一个Parse类的对象,包含scheme、netloc、path、params、query、fragment六个部分。对比原URL可以看出一个标准的URL链接格式如下:
scheme://netloc/path;params?query#fragment
其中,“//”前面scheme代表协议;第一个“/”符号前面是netloc,即域名,后面是path,即访问路径;“;”后面是params,代表参数;“?”后面是查询条件,一般用作GET类型的URL;“#”后面是锚点,用于在网页内定位页面内部下拉位置。一般的URL都会符合这个规则,利用urlparse()就可以将它们拆分开来。
urllib.parse.ParseResult是一个元祖类型,可以按列表来操作。
2.urlunparse()
即为urlparse()的逆操作。
3.urlsplit()
与urlparse()相似,不单独解析params部分,并入path,也就是长度为5
4.urljoin()
urljoin("base_url","new_url")
将base_url和new_url两个url拼接在一起,原则是base_url只提供三项内容:scheme、netloc、path。如果这三项在链接里不存在,则使用base_url里的自动补充,若果存在,则使用new_url里的对应内容。base_url里面的params、query、fragment是不起热河作用的。
5.urlencoden()
直接上用法:
from urllib.parse import urlencode
params = {
'name':'Merry',
'age':18
}
base_url = "https://www.baidu.com?"
url = base_url + urlencode(params)
print(url)
输出结果为:https://www.baidu.com?name=Merry&age=18 encode()函数将参数字典先序列化为GET请求参数。
6.quote()
from urllib.parse import quote
key = "你好"
url = "www.baidu.com/s?wd=" + quote(key)
print(url)
www.baidu.com/s?wd=%E4%BD%A0%E5%A5%BD
此函数将内容妆花为URL编码的格式,此函数解决URL带有中文参数可能引起的乱码问题。其逆向操作是unquote()
此外,还有urlsplit(),parse_qs(), parse_qsl()等函数,不再详述。