一 爬虫基本库
Python提供了功能齐全的类库来帮助我们完成网络请求。最基础的HTTP库有urllib、httplib2、requests、treq等。
urllib库,只需要关心请求的链接是什么,需要传的参数是什么以及可选的请求头设置就好了,不用深入到底层去了解它到底是怎样传输和通信的。有了它,两行代码就可以完成一个请求和响应的处理过程,得到网页内容。
二 urllib介绍
在Python 2中,有urllib和urllib2两个库来实现请求的发送。而在Python 3中,已经不存在urllib2这个库了,统一为urllib,其官方文档链接为:https://docs.python.org/3/library/urllib.html。
urllib库:Python内置的HTTP请求库,也就是说不需要额外安装即可使用。
它包含如下4个模块。
三 urllib库的urlopen介绍
1 urlopen()
1.1 点睛
urllib.request模块提供了最基本的构造HTTP请求的方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理授权验证(authenticaton)、重定向(redirection)、浏览器Cookies以及其他内容。
1.2 代码
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.read().decode('utf-8'))
1.3 结果
2 结果类型分析
2.1 点睛
urlopen返回的是HTTPResposne类型的对象。
它主要包含read()、readinto()、getheader(name)、getheaders()、fileno()等方法,以及msg、version、status、reason、debuglevel、closed等属性。
得到这个对象之后,我们把它赋值为response变量,然后就可以调用这些方法和属性,得到返回结果的一系列信息了。
例如,调用read()方法可以得到返回的网页内容,调用status属性可以得到返回结果的状态码,如200代表请求成功,404代表网页未找到等。
2.2 代码
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(type(response))
2.3 结果
E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_1_1.py
3 HTTPResposne的属性和方法。
3.1 代码
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
# 前两个输出分别输出了响应的状态码和响应的头信息,
# 最后一个输出通过调用getheader()方法并传递一个参数Server获取了响应头中的Server值,
# 结果是nginx,意思是服务器是用Nginx搭建的。
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))
3.2 结果
E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_1_1.py
200
[('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'SAMEORIGIN'), ('x-xss-protection', '1; mode=block'), ('X-Clacks-Overhead', 'GNU Terry Pratchett'), ('Via', '1.1 varnish'), ('Content-Length', '48960'), ('Accept-Ranges', 'bytes'), ('Date', 'Sun, 06 Jan 2019 07:07:47 GMT'), ('Via', '1.1 varnish'), ('Age', '2563'), ('Connection', 'close'), ('X-Served-By', 'cache-iad2151-IAD, cache-hnd18733-HND'), ('X-Cache', 'HIT, HIT'), ('X-Cache-Hits', '1, 1970'), ('X-Timer', 'S1546758468.685275,VS0,VE0'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
nginx
4 urlopen函数data参数分析
4.1 函数原型
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
4.2 data参数
data参数是可选的。如果要添加该参数,并且如果它是字节流编码格式的内容,即bytes类型,则需要通过bytes()方法转化。另外,如果传递了这个参数,则它的请求方式就不再是GET方式,而是POST方式。
4.3 代码
import urllib.parse
import urllib.request
# 这里我们传递了一个参数word,值是hello。它需要被转码成bytes(字节流)类型。
# 其中转字节流采用了bytes()方法,该方法的第一个参数需要是str(字符串)类型,
# 需要用urllib.parse模块里的urlencode()方法来将参数字典转化为字符串;
# 第二个参数指定编码格式,这里指定为utf8
data = bytes(urllib.parse.urlencode({'word': 'hello'}), encoding='utf8')
# 这里请求的站点是httpbin.org,它可以提供HTTP请求测试。
# 本次我们请求的URL为http://httpbin.org/post,这个链接可以用来测试POST请求,
# 它可以输出请求的一些信息,其中包含我们传递的data参数。
response = urllib.request.urlopen('http://httpbin.org/post', data=data)
print(response.read())
4.4 结果
{
"args": {},
"data": "",
"files": {},
"form": {
"word": "hello"
},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "10",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.5"
},
"json": null,
"origin": "123.124.23.253",
"url": "http://httpbin.org/post"
}
4.5 说明
我们传递的参数出现在了form字段中,这表明是模拟了表单提交的方式,以POST方式传输数据。
5 urlopen函数timeout参数分析
5.1 点睛
timeout参数用于设置超时时间,单位为秒,意思就是如果请求超出了设置的这个时间,还没有得到响应,就会抛出异常。如果不指定该参数,就会使用全局默认时间。它支持HTTP、HTTPS、FTP请求。
5.2 实例
import urllib.request
# 这里我们设置超时时间是0.1秒
response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
print(response.read())
5.3 结果
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "/var/py/python/urllibtest.py", line 4, in
...
urllib.error.URLError:
5.4 结果说明
这里我们设置超时时间是0.1秒。程序0.1秒过后,服务器依然没有响应,于是抛出了URLError异常。该异常属于urllib.error模块,错误原因是超时。
5.5 捕获异常实战
import socket
import urllib.request
import urllib.error
# 这里我们请求了http://httpbin.org/get测试链接,
# 设置超时时间是0.1秒,然后捕获了URLError异常,
# 接着判断异常是socket.timeout类型(意思就是超时异常),
# 从而得出它确实是因为超时而报错,打印输出了TIME OUT
try:
response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
except urllib.error.URLError as e:
if isinstance(e.reason, socket.timeout):
print('TIME OUT')
5.6 结果
E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_1_1.py
TIME OUT
6 其他参数
除了data参数和timeout参数外,还有context参数,它必须是ssl.SSLContext类型,用来指定SSL设置。
此外,cafile和capath这两个参数分别指定CA证书和它的路径,这个在请求HTTPS链接时会有用。
cadefault参数现在已经弃用了,其默认值为False。
urlopen()可以完成简单的请求和网页抓取。
若需更加详细的信息,可以参见官方文档:https://docs.python.org/3/library/urllib.request.html。