Python 网络爬虫从0到1 (1):Requests库入门详解

  网络爬虫中,网络请求是基础部分。没有网络请求以及响应,网络爬虫的后续数据分析也就失去了意义。Python中的网络请求,主要由Requests库来完成,本篇,我们就来一起认识一下Requests库及其基本使用方法。

Requests入门

Requests库简介

  Requests库是一个简洁而优雅的Python第三方库,更好地贴合人们的使用习惯,故在http类库中,Requests库非常受开发者青睐。Requests库支持Keep-Alive持久化连接、带有Cookie的对话、SSL认证、动解码、HTTP(S)代理支持、流下载、文件分块上传等当今使用的诸多功能。其他功能介绍和说明文档参见官方文档。Requests: HTTP for Humans

 Requests库的安装

pip install requests

 Requests库的主要方法

Requests库主要有7个方法,大部分与HTTP(S)协议中的请求方法相同

方法说明
requests.request()构造一个请求以支撑以下各个方法
requests.get()获取资源的方法,同HTTP GET
requests.head()获取资源响应头部信息的方法,同HTTP HEAD
requests.post()向网站提交post请求的方法,同HTTP POST
requests.put()向网站提交put请求的方法,同HTTP PUT
requests.patch()向网站提交patch局部修改请求,同HTTP PATCH
requests.delete()向网站提交删除资源请求,同HTTP DELETE
  • 另外,其他的HTTP方法requests库也都支持,由于不常用就不一一列举

  • 实际上,所有的其他方法都是通过调用基本方法requests.request()实现的


使用Requests库构造基本请求

  网页访问中最常用的请求方法是GET方法,下面我们就使用GET方法构造一个基本的请求。

 Requests.get()方法

通过以下代码

r = requests.get(url)
#url是一个字符串型变量,保存了要请求资源的URL

Requests库构造了一个向服务器请求资源的Request请求对象,该命令返回的结果是一个包含服务器资源的Response响应对象r

Requests.get()方法的完整使用格式

requests.get(url,params=None,**kwargs)

其中:

  • url: 想要请求的资源的URL,统一资源定位符
  • params: 可选,默认为None,表示在url中的额外参数,可以是字典或字节流格式。
  • **kwargs: 可选,12个控制访问的参数,见下

实际上,requests.get()方法调用了requests.request()方法,封装前代码如下

requests.request('get',url,params=params,**kwargs)

get方法将params参数作为含有默认参数的关键字参数单独列出,所以,requests.request()方法一共有13个参数(包含params),以字典方式读入。

 Response响应对象

上述请求返回了一个Response响应对象,包含了从服务器返回的资源相关信息,主要具有如下属性

属性说明
r.status_codeHTTP请求返回状态码
r.textHTTP响应内容(字符串形式)
r.encoding由HTTP header得到的响应主体编码方式,也为当前实体编码方式(也可以通过后期配置)
r.apparent_encoding从响应主体中分析得到的编码方式(备选)
r.contentHTTP响应内容的二进制形式

 使用get方法构造请求

下面用一个样例来说明如何使用requests.get()方法构造一个get请求,以访问百度为例

r = requests.get("https://www.baidu.com")

查看响应对象的编码信息

#每一行后的注释内容为返回值
r.encoding
#'ISO-8859-1'
r.apparent_encoding
#'utf-8'

实际上,从响应头部字段中得到的主体编码格式(事实上,响应头部没有指定编码格式时,默认格式即为ISO-8859-1)是错误的(无法正确显示中文),需要自己调整·r.encoding为其主体实际编码utf-8,才能正确显示中文

正确设定主体的编码格式后,就可以正确得到响应的主体内容,另外还可获取响应头部信息等


爬取网页的通用代码框架

  通用代码框架是用来爬取网页的一段通用代码,通过对爬取网页的通用代码框架的定制可以可靠而灵活地爬取网页内容,也能够获得通向其他页面的链接。在使用requests.get()方法访问网页时难免会抛出异常,所以在学习通用代码框架前还要了解Requests库的异常信息以及处理方法。

 Requests库的异常处理

  使用Requests库发送请求时可能会收到来自各个环节的各种异常,若不加以处理,可能会导致程序异常终止。所以认识和处理异常是爬虫开发中必需的环节。

异常说明
requests.ConnectionError网络连接错误,如无法建立连接、DNS解析错误、连接被拒绝(非4xx响应代码)等
requests.HTTPErrorHTTP错误异常(需要手动抛出,见注释)
requests.URLRequired缺失URL异常
requests.TooManyRedirects响应的重定向超过阈值,产生重定向异常
requests.ConnectTimeout服务器连接超时异常
requests.Timeout请求超时(非连接超时,指连接后的请求阶段超时)
  • 其中,ConnectionError指在网络TCP层产生的异常,这类异常会强制终止程序;而HTTPError指在HTTP协议(应用层)产生的异常,使用r.raise_for_status()方法手动抛出异常,只要返回代码非200,就会抛出这个异常。

 通用代码框架

import requests


def get_uri(url):
    try:
        r = requests.get(url, allow_redirects=False)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "An error has been thrown"


print("Requests.get Skeleton")
print(get_uri("http://192.168.0.6:8080/a"))

  • 示例中的get_uri函数即为封装完成的简单爬虫通用代码框架
  • 示例中,服务器返回了404错误,被raise_for_status()方法捕获;若将示例中的url改为一个不存在的服务器或非法url,不需要该语句也会直接抛出错误。在经过try-except语句的异常捕获后,程序不会退出,而可以进行下一步程序内错误提示与处理。
  • 如果将示例中的url改为真实存在的,则会直接输出网页源代码,可以通过进一步操作解析处理。
  • 对except语句捕获条件的更精确定义可以区分不同的错误,从而对不同错误定制不同的解决办法

Requests库主要方法的使用

 request基本方法与参数

首先介绍一下Requests库的基本方法——Requests.request()方法,Requests库中的其他主要请求方法都是通过调用Requests.request()方法完成的

requests.request('Method', url, **kwargs)

其中

  • Method为指定的方法名称
  • url为请求的目标资源统一标识符
  • **kwargs为请求附加的其他参数,其他所有基于requests.request()的方法参数与其相同,有部分方法可能将部分常用参数作为关键字参数显式定义,没有较大影响
参数说明
params作为参数加入到要访问的url链接中
data作为Request报文主题内容,以表单形式传送,可以为字典,元组等
jsonjson格式的Request报文内容
headers较常用,定义了Request报文的请求头部参数,可以为字典
cookiesHTTP Request中的cookie信息,可为字典、CookieJar或Request中的Cookie
auth用于HTTP协议认证,为元组
filesRequest报文主体(以文件形式),为字典,字典的Key为文件类型变量
timeout设置Request的超时时间,单位为秒
proxies设置访问的代理服务器,为字典,分别为协议指定代理服务器
allow_redirects允许重定向,boolean型,默认True,允许重定向
stream流下载(获取内容立即下载),boolean型,默认True,允许流下载
verifySSL认证证书开关,默认True,使用SSL认证证书
cert本地的SSL证书路径
  • 注意:data参数是将参数加入Request报文中,而params参数是将参数加入要访问的url链接中。比如,params={‘a’: 1},url='https://www.baidu.com/',最后请求生成的url为'https://www.baidu.com/?a=1'

  • headers是一个常用参数,用于定义请求报文的头部信息,接受字典形式的数据。如果未经定义,会输出默认参数

    {'User-Agent': 'python-requests/2.24.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
    
  • files参数示例

    files = {'file1': open('data.xls', 'rb')}
    r = requests.post{'https://192.168.0.6:8080/post', files=files}
    
  • proxies示例

    proxies = {'http': 'http://192.168.0.4',
              'https': 'https://192.168.0.5'}
    

关于get方法,上文已经做过讲解,本段中不再重复赘述,下面介绍一些其他的requests库方法

 Requests.post()方法

Requests.post()方法通过HTTP协议的post方法向服务器传递数据,关于HTTP中的post方法请读者自行了解,下面仅介绍Requests.post()方法的具体使用

post方法的封装

def post(url, data=None, json=None, **kwargs):
    r"""Sends a POST request.

    :param url: URL for the new :class:`Request` object.
    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
        object to send in the body of the :class:`Request`.
    :param json: (optional) json data to send in the body of the :class:`Request`.
    :param \*\*kwargs: Optional arguments that ``request`` takes.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response
    """

    return request('post', url, data=data, json=json, **kwargs)

可以看到,post方法将datajson参数单独列出,分别表示post请求主体内容(以web表单形式编码)和以json格式编码的主体内容。以web表单形式编码的条件为data是一个字典;如果想要发送未经编码的数据(不要默认web表单编码),则直接以字符串作为data

下面三个示例分别用web表单格式、json格式和****作为post方法的请求主体,后附服务器收到信息(节选)

payload = {'b': 2}
r = requests.post("http://192.168.0.6:8080/post", data=payload)

import json
payload = {'b': 2}
r = requests.post("http://192.168.0.6:8080/post", json=json.dumps(payload))

r = requests.post("http://192.168.0.6:8080/post", data="b=2")

{"args":{},"data":"\"{\\\"b\\\": 2}\"","files":{},"form":{},"headers":{"Content-Length":"12","Content-Type":"application/json"},"json":"{\"b\": 2}",}

{"args":{},"data":"","form":{"b":"2"},"headers":{"Content-Length":"3","Content-Type":"application/x-www-form-urlencoded"},"json":null}

{"data":"b=2","headers":{"Content-Length":"3"},"json":null}
  • 在发送未经编码的请求实体时,首部字段中不存在Content-Type

    如果以元组作为data,将同样以web表单形式编码,但是如果当个元组使用同一个key的时候,使用元组可以避免字典中键名称重复的问题

payload = (('b', 1), ('b', 2))
r = requests.post("http://192.168.0.6:8080/post", data=payload)

#下面是服务器收到的主体内容
"form":{"b":["1","2"]}

 Requests.put()方法

HTTP协议中put方法与post方法基本类似,只是使用put方法时会将该url下原有数据覆盖,而post方法只是新增一个数据。在Requests库中两个方法的格式几乎相同,这里就不再赘述。

 Requests.patch()方法

于HTTP协议中的patch方法类似,用法类似于Requests.put(),区别在于patch仅提供需要修改的部分数据,而put需要提交在该url下的全部数据。

 Requests.delete()方法

与HTTP协议中的delete方法类似,能够请求服务器删除url所指定的资源,可能需要在请求参数中加入认证信息。

 Requests.head()方法

与HTTP协议中的head方法类似,用法类似于Requests.get()方法,区别仅在于返回报文中只有头部信息而没有主体。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值