本文主要是为了记录网络爬虫学习过程中的笔记和自己的一丢丢理解,希望可以通过本文以及如果有后续文章的话,能够掌握网络数据爬虫和网页解析的基本能力。
本文主要是参考了MOOC-北京理工大学的网络爬虫的课程。
一、准备工作
1. 安装anaconda
即便已经安装了python也建议安装anaconda,因为Anaconda 附带了一大批常用数据科学包,而且anaconda是建立在conda(包管理器和环境管理器)上的,她可以管理包(安装、卸载、更新包),还可以管理环境,比如python2, python3,同时安装两个版本的python可能造成混乱,又或者你希望一个环境是用tensorflow1.0版本的,另一个用tensorflow2.0版本,这样就可以在对应环境下处理不同需求的任务了。总之,conda是一个非常不错的工具。
2. 安装爬虫需要的Requests库
Requests是一个基于Apache2协议开源的Python HTTP库,总之是进行网络爬虫时必备的一个库文件。
因为我用了conda,所以我的命令是:
conda install requests
如果没有安装conda或者不用conda的命令,也可以pip的方式:
pip install requests
3. 测试安装是否成功
1 | import requests |
打印的结果如下:
以上则说明安装成功!:)
二、Requests库
1.Response对象
在上一节中第3小节中,可以看到获取网页资源的方法就是:
r = requests.get(url)
这里.get(url)
相当于构造了一个向服务器请求资源的Request对象,其返回的内容的为r,这是Response对象,包含服务器所含的所有相关资源。
这里我们重点介绍一下Response对象。
同样在上一节我们已经看到了Response对象的一个属性,r.status_code
用于检测请求状态,返回200说明访问成功。那么我们需要了解到Response对象的几个重要的属性:
属性 | 说明 |
---|---|
r.status_code | HTTP请求的返回状态,200表示连接成功,404表示失败 |
r.text | HTTP响应内容的字符串形式,即url对应的页面内容 |
r.encoding | 从HTTP header中猜测的响应内容编码方式 |
r.apparent_encoding | 从内容中分析出的响应内容编码方式(备选编码方式) |
r.content | HTTP响应内容的二进制形式 |
其中r.text
是根据r.encoding
显示网页内容的,并且r.encoding
是用于告知网站的编码方式,如果在header中不存在charset字段,那么编码默认为ISO-8859-1,而r.apparent_encoding
是根据网页内容分析出的编码方式。如执行下述操作,可以看出这两种的不同:
1 | import requests |
如果直接利用第一种编码方式输出r.text
的话返回的是乱码,但是如果我们通过设置r.encoding
为分析出的'utf-8'
的话,那么r.text
返回的就会包含百度页面的一些中文字,是我们能看懂的一些东西。
这里还要再科普一下各种编码方式,下面的东西是我在一个博客zhanghuaichao上看到的,我简单的整理了一下,缩短了这个故事:
首先最一开始计算机在美国广泛使用,其用来存储英语的文字时,设计了叫ANSI的Ascii编码,一共有127号。后来世界各国都开始使用计算机,但是很多国家文字不是英文,ASCII里面没有,于是利用127号之后的空位来表示新的字母、符号,从128到255被称为扩展字符集。这时已经占满了可表示的所有状态。
等后来中国人用计算机时,由于汉字数量十分多,于是人们巧妙的利用两个大于127的字符连接在一起的时候表示一个汉字,这样的组合就能够满足大约7000多个简体汉字了。在这些编码里,还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。于是这种汉字编码方案就被称为“GB2312”,是对 ASCII 的中文扩展。后来这个方案还是不够用,于是不在要求低字节的是127号之后的码了,只要第一个字节大于127就表示这是一个汉字的开始。这就被称为了GBK标准,其在GB2312基础上又增加了近20000个新的汉字。少数民族的语言加入进来以后,GBK扩展成了GB8030。中国的程序员们就叫这一系列汉字编码为 "DBCS"(Double Byte Charecter Set 双字节字符集)。
由于每个国家都和中国一样有一套这样的编码标准,所以谁都不理解谁,针对不同编码方式的东西还要下载相应的字符系统,非常麻烦,于是这时,一个叫 ISO (国际标准化组织)的国际组织决定着手解决这个问题。他们废了所有的地区性编码方案,重新搞一个包括了地球上所有文化、所有字母和符号的编码,也就是如今的"UNICODE"。UNICODE 是用两个字节来表示为一个字符,他总共可以组合出65535不同的字符。
UNICODE 来到时,一起到来的还有计算机网络的兴起,UNICODE 如何在网络上传输也是一个必须考虑的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,UTF8就是每次8个位传输数据。UTF-8就是在互联网上使用最广的一种unicode的实现方式。
那么这里面似乎没有提到ISO-8859-1,这个单字节编码,此字符集主要支持欧洲使用的语言。
所以不难知道为什么我们get百度的资源时,如果不指定r.encoding
,就会乱码了,因为百度中的中文字符编码方式是不同的。
2.Requests库异常
在爬取过程中,同我们写程序一样,都会遇到各种各样的异常问题,这就需要我们理解并处理好这些异常情况,从而可以帮助我们更好的爬取网页。
Requests库的异常
异常 | 说明 |
---|---|
requests.ConnectionError | 网络链接错误异常,如DNS查询失败、拒绝连接等 |
requests.HTTPError | HTTP错误异常 |
requests.URLRequired | URL缺失异常 |
requests.TooManyRedirects | 超过最大重定向次数、产生重定向异常 |
requests.ConnectTimeout | 连接远程服务器超时异常 |
requests.Timeout | 请求URL超时,产生超时异常 |
这里在补充一些额外小知识:
- 重定向是指假设你现在所处的位置是一个论坛的登录百页面,你填写了帐号,密码,点击登陆,如果你的帐号密码正确,就自动跳转到论坛的首页,不正确就度返回登录页;这里的自动跳转,就是重定向的意思。或者可以说,重定向就是,在网页上设置一个约束条件,条件满足,就自动转入到其它网页、网址。
- ConnectTimeout和Timeoout区别:
- connectTimeout: 仅连接服务器时超过一定时间。
- Timeout: 从访问请求发出到获取网页资源超过一定时间。
捕获上述异常状态时可以用到r.raise_for_status()
来表示。如果状态不是200,那么就为引发异常。由此为了确保稳定安全的网络爬取,这里给出了一个通用的爬取框架:
1 | import requests |
3. HTTP协议和Requests库方法
在一开始安装Requests库时提到Requests是一个基于Apache2协议开源的Python HTTP库,这其中的HTTP(Hypertext Transfer Protocol)是指互联网的超文本传输协议,我们可以利用HTTP协议对网络资源进行一系列的操作(请求资源、删除资源等)。
HTTP是基于请求和响应模式的、无状态的应用层协议,理解起来就是用户发出请求,服务器作出响应,无状态指请求之间没有关联。
HTTP采用URL作为定位网络资源的标识符,URL是通过HTTP协议存取资源的Internet路径,一个URL对应一个数据资源,其格式如下:
http://host[:post][path]
host
: 合法的Internet主机域名或ip地址 port
: 端口号,缺省为80 path
: 请求资源的路径
综上我理解的就是,Requests库可以理解成一个专门应用在HTTP协议上的工具,从而使得HTTP协议可以通过URL来完成对网络资源的获取和管理。
HTTP方法 | Request方法 | 说明 |
---|---|---|
GET | requests.get() | 获取URL位置资源(全部资源) |
HEAD | requests.head() | 获取URL位置资源的头部信息 |
POST | requests.post() | 向URL位置后的资源附加新的数据 |
PUT | requests.put() | 向URL位置存储一个资源,覆盖原URL位置的资源 |
PATCH | requests.patch() | 局部更新URL位置的资源,改变该处资源的部分内容 |
DELETE | requests.delete() | 删除URL位置存储的资源 |
注意:
- 如果资源很大的时候,GET就不合适了,可以获取HEAD信息,提前分析资源的内容。
- PUT和PATCH,PUT是修改了全部字段,而PATCH只是修改了部分指定字段
4. Requests库方法详解
requests.request(method, url, **kwargs)
method: 请求方式,对应get/head/post/put/patch/delete/options,共7个。
- 例:
r = requests.request('GET', url, **kwargs)
- OPTIONS这个方式用的比较少,所以这里不多做介绍。
- 各种请求方式也可以直接利用封装好的方法,如:
r = requests.get(url, **kwargs)
- 例:
url: 页面的链接地址。
**kwargs: 控制访问的参数,均为可选项,共13个。
params: 字典或字节序列,作为参数增加到url中。
- ```python >>> import requests >>> url = "http://www.baidu.com" >>> kv = {'key1':'value1', 'key2':'value2'} >>> r = requests.get(url, params=kv) >>> print(r.url) http://www.baidu.com/?key1=value1&key2=value2
1
2
3
4
5
6
7
8
9
10
- 根据上面的这个例子,我们可以看到一些参数添加到了url链接中,那么实际情况下,就可以根据这些关键字筛选部分资源返回来。
- data:字典,字节序列或文件对象,作为Request的内容。
- 作用:向服务器提交资源时使用,把提交的内容存放到指定的url位置中。
- ```python
>>> body = '主体内容'
>>> r = requests.post(url, data=body)
- ```python >>> import requests >>> url = "http://www.baidu.com" >>> kv = {'key1':'value1', 'key2':'value2'} >>> r = requests.get(url, params=kv) >>> print(r.url) http://www.baidu.com/?key1=value1&key2=value2
json: JSON格式的数据,作为Request的内容
其作用也可以提交资源
```python >>> kv = {'key1':'value1', 'key2':'value2'} >>> r = requests.post(url, json=kv)
1
2
3
4
5
6
- headers: 字典, HTTP定制头
- ```python
>>> hd = {'user-agent':'Chrome/10'} # 用Chrome10版本访问url
>>> r = requests.get(url, headers=hd)上述例子中就是模拟用不同浏览器访问url。
cookies: 字典或CookieJar, Request中的cookie。从HTTP协议中解析cookies。
auth: 元组,支持HTTP认证功能。
cookies和auth都是HTTP高级功能。
files: 字典类型,传输文件。
- ```python >>> fs = {'file':open('data.xls','rb')} >>> r = requests.post(url, files=fs)
1
2
3
4
5
6
7
- timeout: 设定超时时间,秒为单位
- 如果超时会返回一个timeout异常。
- ```python
>>> r = requests.get(url, timeout=10)
- ```python >>> fs = {'file':open('data.xls','rb')} >>> r = requests.post(url, files=fs)
proxies: 字典类型,设定访问代理服务器,可以增加登录认证
- 设定访问的代理服务器,这样在访问url链接时,就是用的代理服务器的地址,可以有效防止爬虫逆追踪。
allow_redirects: True/False,默认为True,重定向开关。
stream: True/False,默认为True,获取内容立即下载开关。
verity: True/False默认Ture,认证SSL证书开关。
cert: 本地SSL证书路径。
上述四个字段对应的都是一些高级功能,暂不需了解。
上述介绍了很多,但是其实我们最常使用的就是get方法和head方法,以及一些常见参数的应用。
哇终于码完了第一篇关于爬虫的文章,希望还有后续啊!!!本来一开始学爬虫是为了解决点自己的一些任务,结果手动任务解决完了,爬虫才学了一个get网页资源。。。
不过,无论怎么说,爬虫还是蛮有用的,不知道以后还有没有机会用,不过必要时候可以装一装。自己也是懂爬虫的人啦!