站点图标 兰玉磊的个人博客

Requests库的使用

HTTP协议

在开始介绍Requests库和爬虫之前,首先需要先多了解了解HTTP协议,这里就不过多的介绍了,有熟悉HTTP的可以略过,不熟悉的HTTP的可以点击下面地址,去详细的了解以下。

关于HTTP协议,一篇就够了

HTTP 协议入门- 阮一峰的网络日志

超文本传输协议- 维基百科,自由的百科全书

http_百度百科

同时推荐一个学习HTTP的书,HTTP权威指南

Requests介绍及基本使用

Requests是一个简单且优雅的Python HTTP库,相较于Python标准库中的urllib和urllib2的库,Requests更加的便于理解使用。

Requests是Python的第三方库,也是目前公认爬取网页最好的第三方库,使用起来非常简单,简洁。

Requests的安装

# 直接使用pip进行安装即可
pip install requests

Requests安装非常简单,有任何问题,可通过官网查询学习。

https://requests.readthedocs.io/zh_CN/latest/

检查Requests是否安装成功

>>> import requests
>>> r = requests.get("https://fdevops.com")
>>> r.status_code
200
>>> r.encoding = 'utf-8'
>>> r.text
'<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"><meta name="renderer" content="webkit"><meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1,width=device-width"><link media="all" href="https://fdevops.com/wp-content/cache/autoptimize/css/autoptimize_e29d02f3d2c20b556652ce02cee3d2e7.css" rel="stylesheet" /><title>兰玉磊的技术博客</title><meta name="keywords" content="人工智能...

Requests库的7个主要的方法

方法说明
requests.request()构造一个请求,支撑以下各方法的基础方法
requests.get()获取HTML页面的主要方法,对应于HTTP的GET
requests.head()获取HTML页面头信息的方法,对应于HTTP的HEAD
requests.post()向HTML页面提交POST请求的方法,对应于HTTP的POST
requests.put()向HTML页面提交PUT请求的方法,对应于HTTP的PUT
requests.patch()向HTML页面提交局部修改请求,对应于HTTP的PATCH
requests.delete()向HTML页面提交删除请求,对应于HTTP的DELETE

在Requests库中有两个非常重要的对象,Request和Response。

Requests简单的请求过程

  1. 首先向指定的url发送GET请求,Requests会构造一个向服务器请求资源的Request对象。
  2. 当请求送达后,Requests库会接收到服务器返回的一个包含服务器资源的Response对象,这个Response对象就包含了从服务器返回的所有相关资源,包括请求状态,请求的HTML内容等等。

Response对象最常用的5个属性

属性说明
r.status_codeHTT请求的返回状态,200表示成功,400表示失败,其他状态值,请查看https://fdevops.com/2020/03/14/http-all-code
r.textHTTP响应内容的字符串形式,即URL对应的页面内容
r.encoding从HTTP header中猜测的相应内容编码方式
r.apparent_encoding从内容中分析出的相应内容编码方式(备选编码方式)
r.contentHTTP响应内容的二进制形式

Requests库的方法介绍

requests.request(method, url, **kwargs)

method: 请求方式,对应get/put/post等7种
url: 获取的页面数据的url链接地址
**kwargs: 控制访问的参数,均为可选项,共13个

requests.request() 参数 method的请求方式。

r = requests.request("GET", url, **kwargs)
r = requests.request("HEAD", url, **kwargs)
r = requests.request("POST", url, **kwargs)
r = requests.request("PUT", url, **kwargs)
r = requests.request("PATCH", url, **kwargs)
r = requests.request("DELETE", url, **kwargs)
r = requests.request("OPTIONS", url, **kwargs)

equests.request() 中的url参数就想说了,就是一个你需要爬取的链接地址。

requests.request() 中的**kwargs参数解析。

params: 字典或字节序列,作为参数增加到url中。
    >>> kv = {"a": 1, "b": 2}
    >>> r = requests.request("GET", "https://fdevops.com", params=kv)
    >>> r.url
    'https://fdevops.com/?a=1&b=2'

data: 字典、字节序列或者文件对象,作为Request对象的内容
    >>> kv = {"a": 1, "b": 2}
    >>> r = requests.request("POST", "https://fdevops.com", data=kv)
    >>> body = "测试内容"
    >>> r = requests.request("POST", "https://fdevops.com", data=body.encode('utf-8'))
    >>>

json: JSON格式的数据,作为Request的内容
    >>> kv = {"a": 1, "b": 2}
    >>> r = requests.request("POST", "https://fdevops.com", json=kv)

headers: 字典格式的数据,定制HTTP头数据
    >>> hd = {"user-agent": 'Chrome/10'} # 定制headers里的user-agent
    >>> r = requests.request("POST", "https://fdevops.com", headers=hd)

cookies: 字典或者CookieJar格式,Request中的cookie,从HTTP中解析cookie

auth: 元组,支持HTTP认证功能

files: 字典类型,进行传输文件的时候使用的字段参数
    >>> fs = {"file", open("demo.txt", "rb")}
    >>> r = requests.request("POST", "https://fdevops.com", files=fs)

timeout: 设置超时时间,单位为秒
    >>> r = requests.request("GET", "https://fdevops.com", timeout=10)

proxies: 字典类型,设置访问代理服务器,可以增加登陆认证,可以有效的隐藏源访问的IP地址,有效的防止对爬虫的逆追踪
    >>> pxs = {"http": "http://user:pass@192.168.1.1:8000",
               "https": "https://192.168.1.1:8001"}
    >>> r = requests.request("GET", "https://fdevops.com", proxies=pxs)

allow_redirects: True/False,默认为True,重定向的开关

stream: True/False,默认为True,对获取的内容是否立即下载的开关

verify: True/False,默认为True,认证SSL证书的开关

cert: 本地SSL证书的路径

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

url: 获取的页面数据的url链接地址
params: url中的额外参数,字典或者字节流格式,可选参数
**kwargs: 12个控制访问的参数,请参考requests.requests()的**kwargs参数解析

requests.head(url, **kwargs)

url: 获取的页面数据的url链接地址
**kwargs: 13个访问控制参数,请参考requests.requests()的**kwargs参数解析

requests.post(url, data=None, json=None, **kwargs)

url: 获取的页面数据的url链接地址
data: 字典、字节序列或者文件对象,作为Request对象的内容
json: JSON格式的数据,作为Request的内容
**kwargs: 11个访问控制参数,请参考requests.requests()的**kwargs参数解析

requests.put(url, data=None, **kwargs)

url: 获取的页面数据的url链接地址
data: 字典、字节序列或者文件对象,作为Request对象的内容
**kwargs: 12个访问控制参数,请参考requests.requests()的**kwargs参数解析

requests.patch(url, data=None, **kwargs)

url: 获取的页面数据的url链接地址
data: 字典、字节序列或者文件对象,作为Request对象的内容
**kwargs: 12个访问控制参数,请参考requests.requests()的**kwargs参数解析

requests.delete(url, **kwargs)

url: 获取的页面数据的url链接地址
**kwargs: 13个访问控制参数,请参考requests.requests()的**kwargs参数解析

爬取网页的通用代码结构

在我们写爬虫程序的时候,需要按照一个的顺序去处理程序返回的Response对象属性,如下图所示:

通过实际的例子演示一下

>>> import requests
>>> r = requests.get("https://baidu.com")
>>> r.status_code # 状态码
200
>>> r.text # 网页内容
'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>ç\x99¾åº¦ä¸\x80ä¸\x8bï¼\x8cä½\xa0å°±ç\x9f¥é\x81\x93</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> ...'
>>> r.encoding # 网页编码,若是header中不存在charset字段,则默认为'ISO-8859-1',这种编码格式不支持中文
'ISO-8859-1'
>>> r.apparent_encoding # 根据页面内容得到的编码格式
'utf-8'
>>> r.encoding = r.apparent_encoding # 将编码格式替换成备用的编码格式
>>> r.encoding
'utf-8'
>>> r.text # 用新的编码格式,获取的内容就支持中文了。
'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> ...'
>>>

通过上面的例子,可以看出如果编码不正确则无法正确的解析数据,而出现乱码的情况。

因为r.encoding是通过headers中的charset来得到的,如果headers中存在这个字段则是对应的编码格式,如果没有这个字段呢,则默认是ISO-8859-1,而这种编码格式是无法解析中文,因此会出现中文乱码。

r.apparent_encoding是根据返回的页面数据来获得的备用编码格式的,因此当出现返回乱码的时候,使用r.apparent_encoding替换掉r.encoding即可。

其实严格来说,r.apparent_encodingr.encoding得到的编码格式更加准确,因为r.apparent_encoding会去分析内容,而r.encoding不会,仅仅只是通过headers中`charset`而得到。

编码的简单介绍

Requests中的常用异常

我们在爬取网页的过程中,肯定不会是一直一帆风顺的,会出现各种情况,比如已知网络链接异常,防火墙拦截等等,因此在开发爬虫程序的时候,对异常的处理也是非常重要的,需知道每种异常的处理方式。

Requests库支持的6中常用异常

异常说明
requests.ConnectionError网络连接错误异常,如DNS解析失败,拒绝连接等
requests.HTTPErrorHTTP错误异常
requests.URLRequiredURL缺失异常
requests.TooManyRedirects超过最大重定向次数,产生重定向异常
requests.ConnectTimeout连接远程服务器超时异常
requests.Timeout请求URL超时,产生超时异常

Requests中的异常方法

r.raise_for_status() # 如果不是200,产生异常requests.HTTPError

通过一个实际的例子,演示一下:

import requests

def getHTMLText(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status()  # 如果状态不是200,则引发HTTPError异常
        r.encoding = r.apparent_encoding
        return r.text
    except Exception as e:
        return "产生异常"

if __name__ == '__main__':
    url = "https://baidu.com"
    print(getHTMLText(url))

可以把上面的实例看成一个爬虫代码的简单结构。

退出移动版