Python爬虫学习笔记(2)9.24
【由于内容定位是个人学习笔记,所以并不适合作为系统的学习材料!!!】
1. Handle
和Opener
首先,介绍一下 urllib.request
模块里的 BaseHandler
类,它是所有其他 Handler
的父类,它提供了最基本的方法,例如 default_open()
、protocol_request()
等。
接下来,就有各种 Handler
子类继承这个 BaseHandler
类,举例如下。
HTTPDefaultErrorHandler
:用于处理 HTTP 响应错误,错误都会抛出HTTPError
类型的异常。HTTPRedirectHandler
:用于处理重定向。HTTPCookieProcessor
:用于处理 Cookies。ProxyHandler
:用于设置代理,默认代理为空。HTTPPasswordMgr
:用于管理密码,它维护了用户名和密码的表。HTTPBasicAuthHandler
:用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。
另一个比较重要的类就是 OpenerDirector
,我们可以称为 Opener
。我们之前用过 urlopen()
这个方法,实际上它就是 urllib 为我们提供的一个 Opener
。
之前使用的 Request
和 urlopen()
相当于类库为你封装好了极其常用的请求方法,利用它们可以完成基本的请求,但是现在我们需要实现更高级的功能,所以需要深入一层进行配置,使用更底层的实例来完成操作,所以这里就用到了 Opener
。
Opener
可以使用 open()
方法,返回的类型和 urlopen()
如出一辙。可以利用 Handler
来构建 Opener
。
2. HTTPError
它是 URLError
的子类,专门用来处理 HTTP 请求错误,比如认证请求失败等。它有如下 3 个属性。
code
:返回 HTTP 状态码,比如 404 表示网页不存在,500 表示服务器内部错误等。reason
:同父类一样,用于返回错误的原因。headers
:返回请求头。
下面我们用几个实例来看看:
from urllib import request,error
try:
response = request.urlopen('http://cuiqingcai.com/index.htm')
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep='\n')
有时候,reason
属性返回的不一定是字符串,也可能是一个对象。再看下面的实例:
import socket
import urllib.request
import urllib.error
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')
3. urlparse()
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
该方法可以实现 URL 的识别和分段,这里先用一个实例来看一下:
from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment')
print(type(result), result)
返回结果实际上是一个元组,我们可以用索引顺序来获取,也可以用属性名获取。示例如下:
from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html#comment', allow_fragments=False)
print(result.scheme, result[0], result.netloc, result[1], sep='\n')
4. urlunparse()
有了 urlparse()
,相应地就有了它的对立方法 urlunparse()
。它接受的参数是一个可迭代对象,但是它的长度必须是 6,否则会抛出参数数量不足或者过多的问题。先用一个实例看一下:
from urllib.parse import urlunparse
data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment']
print(urlunparse(data))
这里参数 data
用了列表类型。当然,你也可以用其他类型,比如元组或者特定的数据结构。
5. urlsplit()
这个方法和 urlparse()
方法非常相似,只不过它不再单独解析 params
这一部分,只返回 5 个结果。上面例子中的 params
会合并到 path
中。示例如下:
from urllib.parse import urlsplit
result = urlsplit('http://www.baidu.com/index.html;user?id=5#comment')
print(result)
6. urlunsplit()
与 urlunparse()
类似,它也是将链接各个部分组合成完整链接的方法,传入的参数也是一个可迭代对象,例如列表、元组等,唯一的区别是长度必须为 5。示例如下:
from urllib.parse import urlunsplit
data = ['http', 'www.baidu.com', 'index.html', 'a=6', 'comment']
print(urlunsplit(data))
7. urljoin()
此外,生成链接还有另一个方法,那就是 urljoin()
方法。我们可以提供一个 base_url
(基础链接)作为第一个参数,将新的链接作为第二个参数,该方法会分析 base_url
的 scheme
、netloc
和 path
这 3 个内容并对新链接缺失的部分进行补充,最后返回结果。
下面通过几个实例看一下:
from urllib.parse import urljoin
print(urljoin('http://www.baidu.com', 'FAQ.html'))
print(urljoin('http://www.baidu.com', 'https://cuiqingcai.com/FAQ.html'))
print(urljoin('http://www.baidu.com/about.html', 'https://cuiqingcai.com/FAQ.html'))
print(urljoin('http://www.baidu.com/about.html', 'https://cuiqingcai.com/FAQ.html?question=2'))
print(urljoin('http://www.baidu.com?wd=abc', 'https://cuiqingcai.com/index.php'))
print(urljoin('http://www.baidu.com', '?category=2#comment'))
print(urljoin('www.baidu.com', '?category=2#comment'))
print(urljoin('www.baidu.com#comment', '?category=2'))
可以发现,base_url
提供了三项内容 scheme
、netloc
和 path
。如果这 3 项在新的链接里不存在,就予以补充;如果新的链接存在,就使用新的链接的部分。而 base_url
中的 params
、query
和 fragment
是不起作用的。
通过 urljoin()
方法,我们可以轻松实现链接的解析、拼合与生成。
8. urlencode()
这里我们再介绍一个常用的方法 ——urlencode()
,它在构造 GET 请求参数的时候非常有用,示例如下:
from urllib.parse import urlencode
params = {
'name': 'germey',
'age': 22
}
base_url = 'http://www.baidu.com?'
url = base_url + urlencode(params)
print(url)
9. parse_qs()
有了序列化,必然就有反序列化。如果我们有一串 GET 请求参数,利用 parse_qs()
方法,就可以将它转回字典,示例如下:
from urllib.parse import parse_qs
query = 'name=germey&age=22'
print(parse_qs(query))
10. parse_qsl()
另外,还有一个 parse_qsl()
方法,它用于将参数转化为元组组成的列表,示例如下:
from urllib.parse import parse_qsl
query = 'name=germey&age=22'
print(parse_qsl(query))
11. quote()
该方法可以将内容转化为 URL 编码的格式。URL 中带有中文参数时,有时可能会导致乱码的问题,此时用这个方法可以将中文字符转化为 URL 编码,示例如下:
from urllib.parse import quote
keyword = '壁纸'
url = 'https://www.baidu.com/s?wd=' + quote(keyword)
print(url)
12. unquote()
有了 quote()
方法,当然还有 unquote()
方法,它可以进行 URL 解码,示例如下:
from urllib.parse import unquote
url = 'https://www.baidu.com/s?wd=%E5%A3%81%E7%BA%B8'
print(unquote(url))
内容参考(摘抄)自Python3 网络爬虫开发实战。