python requests库学习

Requests

python的request库官方介绍就是让HTTP服务人类,因此从这点咱们就能够知道request库是为了让咱们更加方便的进行http相关的各类操做html

咱们学习request有什么用呢?node

1)web时代咱们须要熟悉掌握web交互原理python

2)爬虫nginx

3)服务器编程git

4)自动化测试github


实验环境准备

首先是环境的准备,首先咱们确定要装requests库 直接使用pip命令便可(注意:本文使用的是py3.6版本)web

同时咱们须要一个服务器来测试咱们的各类操做,咱们能够直接使用requests库做者写的一个网站 httpbin.org 来进行咱们的各类实验操做编程


 requests例程

咱们能够从下面的简单的例程来简单了解下requestsjson

import requests

#实验web地址 http://httpbin.org
url_ip='http://httpbin.org/ip'
url_get='http://httpbin.org/get'

#直接使用
def requests_simple():
    #利用get方法获得一个response
    response1=requests.get(url_ip)
    #打印头部headders
    print('Response Headers:',response1.headers)
    #打印Body
    print('Response Body:',response1.text)

#带参数的请求
def requests_params():
    params_test={'param1':'hello','param2':'world'}
    #发送请求
    response2=requests.get(url_get,params=params_test)
    #处理响应
    #打印头部headders
    print('Response Headers:', response2.headers)
    #打印Status Code
    print('Response Status Code',response2.status_code)
    # 打印Body  上面用到的是text 咱们能够直接使用 .json()方法获得js格式
    print('Response Body:', response2.json())


if __name__=='__main__':
    print('___________requests_simple方法____________')
    requests_simple()
    print('___________requests_params方法____________')
    requests_params()

看下输出结果:api

___________requests_simple方法____________
Response Headers: {'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', 'Content-Encoding': 'gzip', 'Content-Type': 'application/json', 'Date': 'Tue, 13 Aug 2019 08:21:40 GMT', 'Referrer-Policy': 'no-referrer-when-downgrade', 'Server': 'nginx', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', 'X-XSS-Protection': '1; mode=block', 'Content-Length': '56', 'Connection': 'keep-alive'}
Response Body: {
  "origin": "115.51.238.17, 115.51.238.17"
}

___________requests_params方法____________
Response Headers: {'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', 'Content-Encoding': 'gzip', 'Content-Type': 'application/json', 'Date': 'Tue, 13 Aug 2019 08:21:41 GMT', 'Referrer-Policy': 'no-referrer-when-downgrade', 'Server': 'nginx', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', 'X-XSS-Protection': '1; mode=block', 'Content-Length': '215', 'Connection': 'keep-alive'}
Response Status Code 200
Response Body: {'args': {'param1': 'hello', 'param2': 'world'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.18.4'}, 'origin': '115.51.238.17, 115.51.238.17', 'url': 'https://httpbin.org/get?param1=hello&param2=world'}

程序中每一步都有详细注解,就再也不赘述


 

Requests发送请求

请求方法:

  • GET:    查看资源
  • POST:    增长资源
  • PUT:    修改资源
  • PATCH:     更新资源
  • DELETE:  删除资源
  • HEAD:   查看响应头
  • OPTIONS:  查看可用请求方法

咱们利用github提供的api接口来进行详解 网址https://developer.github.com/v3

咱们先来看下github上对于http请求方法的解释

例程 使用github api接口查看某个用户的公开信息

网址:https://developer.github.com/v3/users/

如图中最后一行显示,咱们可使用 GET /users/:username 来获取信息 下面为代码:

import requests
import json

url='https://api.github.com'

#构建url函数  咱们须要提交的url是原api网址加上咱们本身额外添加的参数
# 因此简单写一个组成url的函数 即添加 '/' 号
def build_url(conend):
    return '/'.join([url,conend])

#更好的显示返回json的打印参数
#咱们从网页获得的json可使用下面函数来更好的print
def better_jsprint(json_str):
    return json.dumps(json.loads(json_str),indent=4)

#主体函数 get请求获得回应  例如咱们查看用户名为Test的公开资料
def requests_method():
    response=requests.get(build_url('users/Test'))
    print(better_jsprint(response.text))

if __name__=="__main__":
    requests_method()

结果返回:

{
    "login": "test",
    "id": 383316,
    "node_id": "MDQ6VXNlcjM4MzMxNg==",
    "avatar_url": "https://avatars3.githubusercontent.com/u/383316?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/test",
    "html_url": "https://github.com/test",
    "followers_url": "https://api.github.com/users/test/followers",
    "following_url": "https://api.github.com/users/test/following{/other_user}",
    "gists_url": "https://api.github.com/users/test/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/test/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/test/subscriptions",
    "organizations_url": "https://api.github.com/users/test/orgs",
    "repos_url": "https://api.github.com/users/test/repos",
    "events_url": "https://api.github.com/users/test/events{/privacy}",
    "received_events_url": "https://api.github.com/users/test/received_events",
    "type": "User",
    "site_admin": false,
    "name": null,
    "company": null,
    "blog": "",
    "location": null,
    "email": null,
    "hireable": null,
    "bio": null,
    "public_repos": 5,
    "public_gists": 0,
    "followers": 23,
    "following": 0,
    "created_at": "2010-09-01T10:39:12Z",
    "updated_at": "2019-02-13T02:44:23Z"
}

这样咱们就获得了名称为Test的用户的公开信息了

一样的咱们也可使用githubapi文档中的其余方法进行测试


 

带参数的请求

首先来看经常使用的带参数请求的三种方法


 

params参数请求例程:

仍是使用github的api接口 此次咱们使用下面这个提供的请求方法 

能够看到该方法中须要传入 params参数 下面是程序代码:

import requests
import json

url='https://api.github.com'

#构建url函数  咱们须要提交的url是原api网址加上咱们本身额外添加的参数
# 因此简单写一个组成url的函数 即添加 '/' 号
def build_url(conend):
    return '/'.join([url,conend])

#更好的显示返回json的打印参数
#咱们从网页获得的json可使用下面函数来更好的print
def better_jsprint(json_str):
    return json.dumps(json.loads(json_str),indent=4)

#主体函数 添加params参数来进行请求
def requests_params():
    response=requests.get(build_url('users'),params={'since':11})
    #打印返回信息
    print (better_jsprint(response.text))
    #查看具体的url地址
    print (response.url)

if __name__=="__main__":
    requests_params()

返回结果很长就再也不展现 只展现下此请求的url地址为 https://api.github.com/users?since=11


 

json参数请求例程

例程1 咱们使用api中更新用户信息的方法来测试json参数请求

下面为代码:

import requests
import json

url='https://api.github.com'

#构建url函数  咱们须要提交的url是原api网址加上咱们本身额外添加的参数
# 因此简单写一个组成url的函数 即添加 '/' 号
def build_url(conend):
    return '/'.join([url,conend])

#更好的显示返回json的打印参数
#咱们从网页获得的json可使用下面函数来更好的print
def better_jsprint(json_str):
    return json.dumps(json.loads(json_str),indent=4)

#主体函数 添加json参数来进行请求 下面代码中的auth用来帐户认证 即本身的帐户密码
def requests_json():
    response=requests.patch(build_url('user'),auth=('此处为你的帐户','此处为你的密码'),json={'name':'此处为你想要改的名字'})
    #打印返回信息
    print (better_jsprint(response.text))
    #查看具体的url地址
    print (response.url)

if __name__=="__main__":
    requests_json()

运行代码以后 咱们能够打开github主页查看本身的帐户名称是否改变

例程2 使用post json参数请求添加一个email地址

代码展现:

import requests
import json

url='https://api.github.com'

#构建url函数  咱们须要提交的url是原api网址加上咱们本身额外添加的参数
# 因此简单写一个组成url的函数 即添加 '/' 号
def build_url(conend):
    return '/'.join([url,conend])

#更好的显示返回json的打印参数
#咱们从网页获得的json可使用下面函数来更好的print
def better_jsprint(json_str):
    return json.dumps(json.loads(json_str),indent=4)

#主体函数 添加json参数来进行请求 代码中的auth参数为认证信息 即本身的github帐户密码 json参数传入要添加的email地址
def requests_json():
    response=requests.post(build_url('user/emails'),auth=('帐户','密码'),json=['test@qq.com'])
    #打印返回信息
    print (better_jsprint(response.text))
    #查看具体的url地址
    print (response.url)

if __name__=="__main__":
    requests_json()

返回内容:

[
    {
        "email": "1231231230@qq.com",
        "primary": true,
        "verified": true,
        "visibility": "private"
    },
    {
        "email": "32220+H3213@users.noreply.github.com",
        "primary": false,
        "verified": true,
        "visibility": null
    },
    {
        "email": "test@qq.com",
        "primary": false,
        "verified": false,
        "visibility": null
    }
]
https://api.github.com/user/emails

至此 咱们已经完成了使用json参数进行请求


 

 请求异常处理

 咱们都知道在互联网上常常会出现不少错误,好比超时,更好比404之类的,当咱们写的程序遇到请求异常该如何处理呢?

咱们以超时(Timeout)和HTTPERR为例写出一个例程来分析:

首先错误都在requests包中的exceptions中 因此咱们要引用:

from requests import exceptions

再例如对于timeout的设置有两种方法:

  • requests.get(url,timeout=(3,7))
  • requests.get(url,timeout=10)

区别是什么呢? 咱们都知道访问一个网站是咱们发送一个请求,而后网站给予咱们一个响应,因此第一种方法中的3和7分别对应这两个过程的超时时间限制,

第二种则是整个访问过程的时间限制

timeout例程:

import requests
import json
from requests import exceptions

url='https://api.github.com'

#构建url函数  咱们须要提交的url是原api网址加上咱们本身额外添加的参数
# 因此简单写一个组成url的函数 即添加 '/' 号
def build_url(conend):
    return '/'.join([url,conend])

#更好的显示返回json的打印参数
#咱们从网页获得的json可使用下面函数来更好的print
def better_jsprint(json_str):
    return json.dumps(json.loads(json_str),indent=4)

#主体函数 添加timeout参数限制访问时间,使用try except来捕获错误并打印
def requests_err():
    try:
        response=requests.get(build_url('user/emails'),timeout=0.1)
    except exceptions.Timeout as err:
        print(err)


if __name__=="__main__":
    requests_err()

返回值:

HTTPSConnectionPool(host='api.github.com', port=443): Max retries exceeded with url: /user/emails (Caused by ConnectTimeoutError(<urllib3.connection.VerifiedHTTPSConnection object at 0x000002990F1A3F28>, 'Connection to api.github.com timed out. (connect timeout=0.1)'))

httperror例程:

httperror例程中咱们能够显式抛出状态值statuscode而后捕获

import requests
import json
from requests import exceptions

url='https://api.github.com'

#构建url函数  咱们须要提交的url是原api网址加上咱们本身额外添加的参数
# 因此简单写一个组成url的函数 即添加 '/' 号
def build_url(conend):
    return '/'.join([url,conend])

#更好的显示返回json的打印参数
#咱们从网页获得的json可使用下面函数来更好的print
def better_jsprint(json_str):
    return json.dumps(json.loads(json_str),indent=4)

#主体函数 下列代码中并未添加认证信息,因此状态值不为200,咱们须要raise出状态值而后捕获
def requests_err():
    try:
        response=requests.get(build_url('user/emails'))
        response.raise_for_status()
    except exceptions.HTTPError as err:
        print(err)

if __name__=="__main__":
    requests_err()

返回值:

401 Client Error: Unauthorized for url: https://api.github.com/user/emails

定制请求

咱们能够自定义构造一些信息而后向目标网址发送来实现某些功能 好比爬虫之类的 下面举简单的修改头部信息

例程:

import requests

#主体函数 在代码中添加头部信息来向目标网址发送本身定制请求
def requests_header():
        response=requests.get('http://httpbin.org/get',headers={'User-Agent':'fake'})
        print(response.text)

if __name__=="__main__":
    requests_header()

看看返回信息:(http://httpbin.org/get 会返回咱们的信息)

{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "fake"
  }, 
  "origin": "115.51.238.17, 115.51.238.17", 
  "url": "https://httpbin.org/get"
}

注意看咱们的头部信息已经完成修改


 

响应的处理 

# 响应的经常使用属性
  response.text # 响应回去的文本(字符串)
  response.content # 响应回去的内容(二进制),通常用来爬取视频
  response.status_code # 响应的状态码
  response.url # 获取请求链接地址
  response.cookies # 获取返回的cookies信息
  response.cookies.get_dict() # 获取返回的cookies信息
  response.request # 获取请求方式
  response.headers # 查看响应头
  response.history # 重定向历史 即前一次请求的地址

# 返回结果为json数据处理
  response.json() # 将结果进行反序列化

# 爬取文档乱码问题
  response.apparent_encoding # 文档的编码的方式(从HTML文档找)
  response.encoding # 响应体编码方式
  eg: response.encoding = response.apparent_encoding # 文档的声明方式
  eg: print(response.text.encode('utf-8'))

 

注意:response.headers是服务器发送给咱们的头部信息,response.request.headers才是咱们这个客服端向服务器发请求的头部信息(即本身的信息)


 

下载文件

例如咱们如今去网络下载一张图片,只不过如今咱们使用requests库来完成

就好比百度官网logo  地址:https://www.baidu.com/img/bd_logo1.png

简单的下载例程以下:

import requests

url='https://www.baidu.com/img/bd_logo1.png'

def download_img():
    response=requests.get(url)
    with open('logo.png','wb') as img:#此步骤涉及文件读写操做 图片是二进制,因此要用二进制写文件 用参数 'wb'
        img.write(response.content)

if __name__=='__main__':
    download_img()

而后会发现当前目录下出现了 logo.png的图片  此时已经下载成功

须要注意的是  有时候文件很大,咱们须要以数据流的方式读写,不然可能形成内存溢出问题,

当下载大的文件的时候,咱们能够在requests.get()中使用stream参数.

默认状况下是false,他会当即开始下载文件并存放到内存当中,假若文件过大就会致使内存不足的状况.

当把get函数的stream参数设置成True时,它不会当即开始下载,当你使用iter_content或iter_lines遍历内容或访问内容属性时才开始下载。须要注意一点:文件没有下载以前,它也须要保持链接。

  • iter_content:一块一块的遍历要下载的内容
  • iter_lines:一行一行的遍历要下载的内容

使用上面两个函数下载大文件能够防止占用过多的内存,由于每次只下载小部分数据。

例程:

import requests

url='https://www.baidu.com/img/bd_logo1.png'

def download_img():
    response=requests.get(url,stream=True)#stream参数记得选为True
    with open('logo.png','wb') as img:#图片是二进制,因此要用二进制写文件 用参数 'wb'
        for chunk in response.iter_content(1024):#规定一次读取写入大小 单位为字节
            img.write(chunk)
        response.close()#关闭数据流链接

if __name__=='__main__':
    download_img()

有时候会被服务器禁止请求,缘由多是user-agent未更改,这就至关于简单的反爬虫了,因此通常咱们写爬虫的时候须要修改user-agent信息,这些问题在讲解爬虫时会讲

简单总结流程就是:

浏览器模拟(修改headers)-->构建request-->读取数据-->写入数据


 

身份认证

auth

前面已经讲过,咱们能够传入 auth 参数来将本身的帐号密码传入目标网址来进行身份验证,但是这种方式是安全的吗?

例如:

import requests

url='https://api.github.com'

#构建url函数  咱们须要提交的url是原api网址加上咱们本身额外添加的参数
# 因此简单写一个组成url的函数 即添加 '/' 号
def build_url(conend):
    return '/'.join([url,conend])

#基础身份认证
def http_auth():
    response=requests.get(build_url('user'),auth=('test','test123'))
    #看下咱们的请求的头部数据
    print(response.request.headers)

http_auth()

咱们再看下返回头部数据:

{'User-Agent': 'python-requests/2.18.4', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Basic dGVzdDp0ZXN0MTIz'}

咱们发现里面含有 'Authorization': 'Basic dGVzdDp0ZXN0MTIz' 一段 那这个会是咱们的帐号密码吗? 咱们使用解码来看下

import base64

print(base64.b64decode('dGVzdDp0ZXN0MTIz'))

输出:

b'test:test123'

发现还真的是咱们的帐号密码,因此这样也不是很安全

所以如今普遍使用更安全的Oauth认证

OAuth

oauth是Open Authorization的简写,oauth协议为用户资源的受权提供了一个安全的、开放而又建议的标准。第三方无需使用用户的用户名与密码就能够申请得到该用户资源的受权,所以oauth是安全的。

最最简单的例子就是 如今咱们登陆多个网站(例如微博,网盘等)应用能够直接选择QQ快速登陆,这就是OAuth认证,它无需你输入帐户密码便可认证

 

下面咱们仍是用github的api来作一个简单的oauth认证  

首先打开github网址:https://github.com/settings/tokens/new 来申请一个本身的令牌认证 记得勾选须要的权限选项

而后咱们就获得了一串神秘代码以下图

接下来咱们开始写简单的例程:

import requests

url='https://api.github.com'

#构建url函数  咱们须要提交的url是原api网址加上咱们本身额外添加的参数
# 因此简单写一个组成url的函数 即添加 '/' 号
def build_url(conend):
    return '/'.join([url,conend])

#基础oauth认证
def http_oauth():
    #构建头部数据 加上token信息
    header={'Authorization':'token 62646e55689b597eb076cb08c5e020e3762bc84f '}
    response=requests.get(build_url('user'),headers=header)
    print(response.text)

http_oauth()

运行发现登陆成功  虽然这是个我的身份令牌 可是oauth原理也是如此


 

Cookie 和 Session

Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(一般通过加密)。

这样作的好处就是cookie的体积变小,只存储session-id信息相似于上面讲的token,而且session信息存储在服务器端也比较安全


 

至此,requests库的学习就先告一段落,可是哦咱们还有更多高阶操做能够去学习。

相关文章
相关标签/搜索