学习爬虫,最初的操作便是来模拟浏览器向服务器发出一个请求,那么我们需要从哪个地方做起呢?请求需要我们自己来构造吗?我们需要关心请求这个数据结构的实现吗?我们需要了解 HTTP、TCP、IP 层的网络传输通信吗?我们需要知道服务器的响应和应答原理吗?
可能你不知道无从下手,不用担心,Python 的强大之处就是提供了功能齐全的类库来帮助我们完成这些请求,最基础的 HTTP 库有 Urllib、Httplib2、Requests、Treq 等。
拿 Urllib 这个库来说,有了它,我们只需要关心请求的链接是什么,需要传的参数是什么以及可选的请求头设置就好了,不用深入到底层去了解它到底是怎样来传输和通信的。有了它,两行代码就可以完成一个请求和响应的处理过程,得到网页内容,是不是感觉方便极了?
接下来,就让我们从最基础的部分开始了解这些库的使用方法吧。
使用Urllib
在 Python2 版本中,有 Urllib 和 Urlib2 两个库可以用来实现Request的发送。而在 Python3 中,已经不存在 Urllib2 这个库了,统一为 Urllib,其官方文档链接为: https://docs.python.org/3/lib...
我们首先了解一下 Urllib 库,它是 Python 内置的 HTTP 请求库,也就是说我们不需要额外安装即可使用,它包含四个模块:
- 第一个模块 request,它是最基本的 HTTP 请求模块,我们可以用它来模拟发送一请求,就像在浏览器里输入网址然后敲击回车一样,只需要给库方法传入 URL 还有额外的参数,就可以模拟实现这个过程了。
- 第二个 error 模块即异常处理模块,如果出现请求错误,我们可以捕获这些异常,然后进行重试或其他操作保证程序不会意外终止。
- 第三个 parse 模块是一个工具模块,提供了许多 URL 处理方法,比如拆分、解析、合并等等的方法。
- 第四个模块是 robotparser,主要是用来识别网站的 robots.txt 文件,然后判断哪些网站可以爬,哪些网站不可以爬的,其实用的比较少。
在这里重点对前三个模块进行下讲解。
发送请求
使用 Urllib 的 request 模块我们可以方便地实现 Request 的发送并得到 Response,我们本节来看下它的具体用法。
1. urlopen()
urllib.request 模块提供了最基本的构造 HTTP 请求的方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理authenticaton(授权验证),redirections(重定向),cookies(浏览器Cookies)以及其它内容。
我们来感受一下它的强大之处,以 Python 官网为例,我们来把这个网页抓下来:
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.read().decode('utf-8'))
看一下运行结果,如图 3-1 所示:
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(type(response))
图 3-1 运行结果
真正的代码只有两行,我们便完成了 Python 官网的抓取,输出了网页的源代码,得到了源代码之后呢?我们想要的链接、图片地址、文本信息不就都可以提取出来了吗?
接下来我们看下它返回的到底是什么,利用 type() 方法输出 Response 的类型。
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(type(response))
输出结果如下:
<class 'http.client.HTTPResponse'>
通过输出结果可以发现它是一个 HTTPResposne 类型的对象,它主要包含的方法有 read()、readinto()、getheader(name)、getheaders()、fileno() 等方法和 msg、version、status、reason、debuglevel、closed 等属性。
得到这个对象之后,我们把它赋值为 response 变量,然后就可以调用这些方法和属性,得到返回结果的一系列信息了。
例如调用 read() 方法可以得到返回的网页内容,调用 status 属性就可以得到返回结果的状态码,如 200 代表请求成功,404 代表网页未找到等。
下面再来一个实例感受一下:
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))
运行结果如下:
200
[('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'SAMEORIGIN'), ('X-Clacks-Overhead', 'GNU Terry Pratchett'), ('Content-Length', '47397'), ('Accept-Ranges', 'bytes'), ('Date', 'Mon, 01 Aug 2016 09:57:31 GMT'), ('Via', '1.1 varnish'), ('Age', '2473'), ('Connection', 'close'), ('X-Served-By', 'cache-lcy1125-LCY'), ('X-Cache', 'HIT'), ('X-Cache-Hits', '23'), ('Vary', 'Cookie'), ('Strict-Transport-Security', &#