Python+Requests接口测试教程(2):requests

开讲前,告诉你们requests有他本身的官方文档:http://cn.python-requests.org/zh_CN/latest/javascript

 

2.1 发get请求

前言
requests模块,也就是老污龟,为啥叫它老污龟呢,由于这个官网上的logo就是这只污龟,接下来就是学习它了。
环境准备(小编环境):
python:2.7.12
pycharm:5.0.4
requests:2.13.0
(这学本篇以前,先要有必定的python基础,由于后面都是直接用python写代码了,小编主要以讲接口为主,python基础东西就本身去补了)
 
1、环境安装html

1.用pip安装requests模块
>>pip install requests前端

2、get请求java

1.导入requests后,用get方法就能直接访问url地址,如:http://www.cnblogs.com/yoyoketang/,看起来是否是很酷
2.这里的r也就是response,请求后的返回值,能够调用response里的status_code方法查看状态码
3.状态码200只能说明这个接口访问的服务器地址是对的,并不能说明功能OK,通常要查看响应的内容,r.text是返回文本信息python

3、params
1.再发一个带参数的get请求,如在博客园搜索:yoyoketang,url地址为:http://zzk.cnblogs.com/s/blogpost?Keywords=yoyoketang
2.请求参数:Keywords=yoyoketang,能够以字典的形式传参:{"Keywords": "yoyoketang"}
3.多个参数格式:{"key1": "value1", "key2": "value2", "key3": "value3"}ajax

4、content
1.百度首页若是用r.text会发现获取到的内容有乱码,由于百度首页响应内容是gzip压缩的(非text文本)正则表达式

 

 2.若是是在fiddler工具乱码,是能够点击后解码的,在代码里面能够用r.content这个方法,content会自动解码 gzip 和deflate压缩数据库

5、response
1.response的返回内容还有其它更多信息json

-- r.status_code     #响应状态码
-- r.content           #字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩
-- r.headers          #以字典对象存储服务器响应头,可是这个字典比较特殊,字典键不区分大小写,若键不存在则返回None
-- r.json()             #Requests中内置的JSON解码器
-- r.url                  # 获取url
-- r.encoding         # 编码格式
-- r.cookies           # 获取cookie
-- r.raw                #返回原始响应体
-- r.text               #字符串方式的响应体,会自动根据响应头部的字符编码进行解码
-- r.raise_for_status() #失败请求(非200响应)抛出异常

2.2 发post请求(json)

前言
发送post的请求参考例子很简单,实际遇到的状况倒是很复杂的,首先第一个post请求确定是登陆了,但登陆是最难处理的。登陆问题解决了,后面都简单了。
 
1、查看官方文档
1.学习一个新的模块,其实不用去百度什么的,直接用help函数就能查看相关注释和案例内容。
>>import requests
>>help(requests)浏览器

 

2.查看python发送get和post请求的案例
       >>> import requests
       >>> r = requests.get('https://www.python.org')
       >>> r.status_code
       200

       >>> 'Python is a programming language' in r.content
       True
    
    ... or POST:
    
       >>> payload = dict(key1='value1', key2='value2')
       >>> r = requests.post('http://httpbin.org/post', data=payload)
       >>> print(r.text)
       {
         ...
         "form": {
           "key2": "value2",

           "key1": "value1"
         },
         ...
       }
 
2、发送post请求
1.用上面给的案例,作个简单修改,发个post请求
2.payload参数是字典类型,传到以下图的form里

3、json
1.post的body是json类型,也能够用json参数传入。
2.先导入json模块,用dumps方法转化成json格式。

3.返回结果,传到data里。

4、headers
1.以博客园为例,模拟登录,实际的状况要比上面讲的几个基本内容要复杂不少,通常登录涉及安全性方面,登录会比较复杂

2.这里需添加请求头headers,能够用fiddler抓包

3.将请求头写成字典格式

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
            "Accept-Encoding": "gzip, deflate, br",
            "Content-Type": "application/json; charset=utf-8",
            "X-Requested-With": "XMLHttpRequest",
            "Cookie": "xxx.............",    # 此处cookie省略了
            "Connection": "keep-alive"
            }

5、登录博客园
1.因为这里是https请求,直接发送请求会报错误:SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
2.能够加个参数:verify=False,表示忽略对 SSL 证书的验证

3.这里请求参数payload是json格式的,用json参数传
4.红色注释那两行能够不用写
5.最后结果是json格式,能够直接用r.json返回json数据:{u'success': True}

6、参考代码

# coding:utf-8
import requests
url = "https://passport.cnblogs.com/user/signin"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
            "Accept-Encoding": "gzip, deflate, br",
            "Content-Type": "application/json; charset=utf-8",
            # "VerificationToken": "",
            "X-Requested-With": "XMLHttpRequest",
            # "Referer": "",  
            "Content-Length": "385",
            "Cookie": "xxx..."# 此处省略
            "Connection": "keep-alive"
            }
payload = {"input1":"xxx",
                 "input2":"xxx",
                 "remember":True}
r = requests.post(url, json=payload, headers=headers,verify=False)
print r.json()

2.3 发post请求(data)

前言:
前面登陆博客园的是传json参数,有些登陆不是传json的,如jenkins的登陆,本篇以jenkins登陆为案例,传data参数。
 
1、登陆jenkins抓包
1.登陆jenkins,输入帐号和密码

2.fiddler抓包

 

3.这个body参数并非json格式,是key=value格式,也就是前面介绍post请求四种数据类型里面的第二种

2、请求头部
1.上面抓包已经知道body的数据类型了,那么头部里面Content-Type类型也须要填写对应的参数类型

 

3、实现登陆
一、登陆代码以下:

 

# coding:utf-8
import requests
# 先打开登陆首页,获取部分cookie
url = "http://localhost:8080/jenkins/j_acegi_security_check"
headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"
           }  # get方法其它加个ser-Agent就能够了
d = {"from": "",
     "j_password": "f7bcd85ebab14e2fbb6d76cc99bc5c6a",
     "j_username": "admin",
     "Jenkins-Crumb": "e677c237181756818cbbccd4296d44f1",
     "json": {"j_username": "admin",
              "j_password": "f7bcd85ebab14e2fbb6d76cc99bc5c6a",
              "remember_me": True,
              "from": "",
              "Jenkins-Crumb": "e677c237181756818cbbccd4296d44f1"},
     "remember_me": "on",
     "Submit": u"登陆"
     }
s = requests.session()
r = s.post(url, headers=headers, data=d)
print r.content

2.打印结果

4、判断登陆是否成功
1.首先这个登陆接口有重定向,看左边会话框302,那登陆成功的结果看最后一个200就行

2.返回的结果并非跟博客园同样的json格式,返回的是一个html页面
 
5、判断登陆成功
1.判断登陆成功,能够抓取页面上的关键元素,好比:帐号名称admin,注销按钮

2.经过正则表达式提出这2个关键字

6、参考代码

# coding:utf-8
import requests
# 先打开登陆首页,获取部分cookie
url = "http://localhost:8080/jenkins/j_acegi_security_check"
headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"
           }  # get方法其它加个ser-Agent就能够了
d = {"from": "",
     "j_password": "f7bcd85ebab14e2fbb6d76cc99bc5c6a",
     "j_username": "admin",
     "Jenkins-Crumb": "e677c237181756818cbbccd4296d44f1",
     "json": {"j_username": "admin",
              "j_password": "f7bcd85ebab14e2fbb6d76cc99bc5c6a",
              "remember_me": True,
              "from": "",
              "Jenkins-Crumb": "e677c237181756818cbbccd4296d44f1"},
     "remember_me": "on",
     "Submit": u"登陆"
     }
s = requests.session()
r = s.post(url, headers=headers, data=d)
# 正则表达式提取帐号和登陆按钮
import re
t = re.findall(r'<b>(.+?)</b>', r.content)   # 用python3的这里r.content须要解码
print t[0]
print t[1]

2.4 data和json傻傻分不清

前言
在发post请求的时候,有时候body部分要传data参数,有时候body部分又要传json参数,那么问题来了:到底何时该传json,何时该传data?
 
1、识别json参数
1.在前面1.8章节讲过,post请求的body一般有四种类型,最多见的就是json格式的了,这个仍是很好识别的

2.用抓包工具查看,首先点开Raw去查看body部分,以下图这种,参数最外面是大括号{   }包起来的,这种已经确诊为json格式了。

 

 3.再一次确认,能够点开Json这一项查看,点开以后能够看到这里的几组参数是json解析后的(记住它的样子)

4.这时候,就能够用前面2.2讲的传json参数

2、识别data参数
1.data参数也就是这种格式:key1=value1&key2=value2...这种格式很明显没有大括号

点开Raw查看,跟上面的json区别仍是很大的

2.由于这个是非json的,因此点开Json这个菜单是不会有解析的数据的,这种数据在WebForms里面查看

3.能够看到这种参数显示在Body部分,左边的Name这项就是key值,右边的Value就是对应的value值,像这种参数转化从python的字典格式就好了

4.这一种发post时候就传data参数就能够了,格式以下:

s = requests.session()
r = s.post(url, headers=headers, data=d)     # 这里的d就是上一步的字典格式的参数

如今能分得清data参数和json参数的不?

2.5 发https请求(ssl)

前言
原本最新的requests库V2.13.0是支持https请求的,可是通常写脚本时候,咱们会用抓包工具fiddler,这时候会 报:requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
小编环境:
python:2.7.12
requests:2.13.0
fiddler:v4.6.2.0
 
1、SSL问题
1.不启用fiddler,直接发https请求,不会有SSL问题(也就是说不想看到SSL问题,关掉fiddler就行)

2.启动fiddler抓包,会出现这个错误:requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)

2、verify参数设置
1.Requests的请求默认verify=True
2.若是你将 verify设置为 False,Requests 也能忽略对 SSL 证书的验证
3.可是依然会出现两行Warning,能够不用管

3、忽略Warning
1.有些小伙伴有强迫症看到红色的内心就发慌,这里加两行代码能够忽略掉警告,眼不见为净!

2.参考代码:

# coding:utf-8
import requests
# 禁用安全请求警告
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
url = "https://passport.cnblogs.com/user/signin"
headers = {
     "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"
          }
r = requests.get(url, headers=headers, verify=False)
print(r.status_code)

2.6 session关联接口

前言
上一篇模拟登陆博客园,但这只是第一步,通常登陆后,还会有其它的操做,如发帖,评论等,这时候如何保持会话呢?
 
1、session简介
1.查看帮助文档,贴了一部分,后面省略了

>>import requests
>>help(requests.session())
class Session(SessionRedirectMixin)
 |  A Requests session.
 |  
 |  Provides cookie persistence, connection-pooling, and configuration.
 |  
 |  Basic Usage::
 |  
 |    >>> import requests
 |    >>> s = requests.Session()
 |    >>> s.get('http://httpbin.org/get')
 |    <Response [200]>
 |  
 |  Or as a context manager::
 |  
 |    >>> with requests.Session() as s:
 |    >>>     s.get('http://httpbin.org/get')
 |    <Response [200]>

2、使用session登陆
1.使用session登陆只需在上一篇基础上稍作修改

# coding:utf-8
import requests
url = "https://passport.cnblogs.com/user/signin"
headers = {
                  #头部信息已省略
                   }
payload = {"input1":"xxx",
                "input2":"xxx",
                "remember":True}
# r = requests.post(url, json=payload, headers=headers,verify=False)
# 修改后以下
s = requests.session()
r = s.post(url, json=payload, headers=headers,verify=False)
print r.json()

3、保存编辑
1.先打开个人随笔,手动输入内容后,打开fiddler抓包

2.把body的参数内容写成字典格式,有几个空的参数不是必填的,能够去掉

body = {"__VIEWSTATE": "",
        "__VIEWSTATEGENERATOR":"FE27D343",
        "Editor$Edit$txbTitle":"这是个人标题:上海-悠悠",
        "Editor$Edit$EditorBody":"<p>这里是中文内容:http://www.cnblogs.com/yoyoketang/</p>",
        "Editor$Edit$Advanced$ckbPublished":"on",
        "Editor$Edit$Advanced$chkDisplayHomePage":"on",
        "Editor$Edit$Advanced$chkComments":"on",
        "Editor$Edit$Advanced$chkMainSyndication":"on",
        "Editor$Edit$lkbDraft":"存为草稿",
         }

3.用上面的session继续发送post请求

4.执行后,查看个人草稿箱就多了一条新增的了

4、参考代码

# coding:utf-8
import requests
url = "https://passport.cnblogs.com/user/signin"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
            "Accept-Encoding": "gzip, deflate, br",
            "Content-Type": "application/json; charset=utf-8",
            # "VerificationToken": "xxx...",  # 已省略
            "X-Requested-With": "XMLHttpRequest",
            # "Referer": 
"https://passport.cnblogs.com/user/signin?ReturnUrl=http%3a%2f%2fmsg.cnblogs.com%2fsend%2f%e4%b8%8a%e6%b5%b7-%e6%82%a0%e6%82%a0",
            "Content-Length": "385",
            "Cookie": "xxx.....",   # 已省略
            "Connection": "keep-alive"
            }
#  登陆的参数
payload = {"input1":"xxx",
           "input2":"xxx",
           "remember":True}
s = requests.session()
r = s.post(url, json=payload, headers=headers,verify=False)
print r.json()
# 保存草稿箱
url2= "https://i.cnblogs.com/EditPosts.aspx?opt=1"
body = {"__VIEWSTATE": "",
        "__VIEWSTATEGENERATOR":"FE27D343",
        "Editor$Edit$txbTitle":"这是个人标题:上海-悠悠",
        "Editor$Edit$EditorBody":"<p>这里是中文内容:http://www.cnblogs.com/yoyoketang/</p>",
        "Editor$Edit$Advanced$ckbPublished":"on",
        "Editor$Edit$Advanced$chkDisplayHomePage":"on",
        "Editor$Edit$Advanced$chkComments":"on",
        "Editor$Edit$Advanced$chkMainSyndication":"on",
        "Editor$Edit$lkbDraft":"存为草稿",
         }
r2 = s.post(url2, data=body, verify=False)
print r.content

这里我是用保存草稿箱写的案例,小伙伴们能够试下自动发帖
(备注:别使用太频繁了哦,当心封号嘿嘿!!!)

2.7 cookie绕过验证码登陆

前言
有些登陆的接口会有验证码:短信验证码,图形验证码等,这种登陆的话验证码参数能够从后台获取的(或者查数据库最直接)。
获取不到也不要紧,能够经过添加cookie的方式绕过验证码。
(注意:并非全部的登陆都是用cookie来保持登陆的,有些是2.11章节讲的token)
1、抓登陆cookie
1.如博客园登陆后会生成一个已登陆状态的cookie,那么只须要直接把这个值添加到cookies里面就能够了。
2.能够先手动登陆一次,而后抓取这个cookie,这里就须要用抓包工具fiddler了

3.先打开博客园登陆界面,手动输入帐号和密码(勾选下次自动登陆)

4.打开fiddler抓包工具,刷新下登陆首页,就是登陆前的cookie了

5.登陆成功后,再查看cookie变化,发现多了两组参数,多的这两组参数就是咱们想要的,copy出来,一会有用

2、cookie组成结构
1.用抓包工具fidller只能看到cookie的name和value两个参数,实际上cookie还有其它参数
2.如下是一个完整的cookie组成结构

cookie ={u'domain': u'.cnblogs.com',
            u'name': u'.CNBlogsCookie',
            u'value': u'xxxx',
            u'expiry': 1491887887,
            u'path': u'/',
            u'httpOnly': True,
            u'secure': False}

name:cookie的名称
value:cookie对应的值,动态生成的
domain:服务器域名
expiry:Cookie有效终止日期
path:Path属性定义了Web服务器上哪些路径下的页面可获取服务器设置的Cookie
httpOnly:防脚本攻击
secure:在Cookie中标记该变量,代表只有当浏览器和Web Server之间的通讯协议为加密认证协议时,
浏览器才向服务器提交相应的Cookie。当前这种协议只有一种,即为HTTPS。

3、添加cookie
1.往session里面添加cookie能够用如下方式
2.set里面参数按括号里面的参数格式

coo = requests.cookies.RequestsCookieJar()  
coo.set('cookie-name''cookie-value', path='/', domain='.xxx.com')  
s.cookies.update(c) 

3.因而添加登陆的cookie,把第一步fiddler抓到的内容填进去就能够了

c = requests.cookies.RequestsCookieJar()
c.set('.CNBlogsCookie', 'xxx')
c.set('.Cnblogs.AspNetCore.Cookies','xxx')
s.cookies.update(c)
print(s.cookies)

4、参考代码

1.因为登陆时候是多加2个cookie,咱们能够先用get方法打开登陆首页,获取部分cookie
2.再把登陆须要的cookie添加到session里
3.添加成功后,随便编辑正文和标题保存到草稿箱

 # coding:utf-8
import requests
# 先打开登陆首页,获取部分cookie
url = "https://passport.cnblogs.com/user/signin"
headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"
           }  # get方法其它加个ser-Agent就能够了
s = requests.session()
r = s.get(url, headers=headers,verify=False)
print s.cookies
# 添加登陆须要的两个cookie
c = requests.cookies.RequestsCookieJar()
c.set('.CNBlogsCookie', 'xxx'# 填上面抓包内容
c.set('.Cnblogs.AspNetCore.Cookies','xxx'# 填上面抓包内容
s.cookies.update(c)
print s.cookies
# 登陆成功后保存编辑内容
url2= "https://i.cnblogs.com/EditPosts.aspx?opt=1"
body = {"__VIEWSTATE": "",
        "__VIEWSTATEGENERATOR":"FE27D343",
        "Editor$Edit$txbTitle":"这是绕过登陆的标题:上海-悠悠",
        "Editor$Edit$EditorBody":"<p>这里是中文内容:http://www.cnblogs.com/yoyoketang/</p>",
        "Editor$Edit$Advanced$ckbPublished":"on",
        "Editor$Edit$Advanced$chkDisplayHomePage":"on",
        "Editor$Edit$Advanced$chkComments":"on",
        "Editor$Edit$Advanced$chkMainSyndication":"on",
        "Editor$Edit$lkbDraft":"存为草稿",
         }
r2 = s.post(url2, data=body, verify=False)
print r.content

2.8 json数据处理

前言
有些post的请求参数是json格式的,这个前面第二篇post请求里面提到过,须要导入json模块处理。
通常常见的接口返回数据也是json格式的,咱们在作判断时候,每每只须要提取其中几个关键的参数就行,这时候就须要json来解析返回的数据了。
1、json模块简介
1.Json简介:Json,全名 JavaScript Object Notation,是一种轻量级的数据交换格式,经常使用于http请求中
2.能够用help(json),查看对应的源码注释内容:

Encoding basic Python object hierarchies::
        >>> import json
        >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
        '["foo", {"bar": ["baz", null, 1.0, 2]}]'
        >>> print json.dumps("\"foo\bar")
        "\"foo\bar"
        >>> print json.dumps(u'\u1234')
        "\u1234"
        >>> print json.dumps('\\')
        "\\"
        >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
        {"a": 0, "b": 0, "c": 0}
        >>> from StringIO import StringIO
        >>> io = StringIO()
        >>> json.dump(['streaming API'], io)
        >>> io.getvalue()
        '["streaming API"]'

2、Encode(python->json)
1.首先说下为何要encode,python里面bool值是True和False,json里面bool值是true和false,而且区分大小写,这就尴尬了,明明都是bool值。
在python里面写的代码,传到json里,确定识别不了,因此须要把python的代码通过encode后成为json可识别的数据类型。
2.举个简单例子,下图中dict类型通过json.dumps()后变成str,True变成了true,False变成了fasle

3.如下对应关系表是从json模块的源码里面爬出来的.python的数据类,通过encode成json的数据类型,对应的表以下:

     |  | Python            | JSON          |
     |  +===================+===============+
     |  | dict              | object        |
     |  +-------------------+---------------+
     |  | list, tuple       | array         |
     |  +-------------------+---------------+
     |  | str, unicode      | string        |
     |  +-------------------+---------------+
     |  | int, long, float  | number        |
     |  +-------------------+---------------+
     |  | True              | true          |
     |  +-------------------+---------------+
     |  | False             | false         |
     |  +-------------------+---------------+
     |  | None              | null          |
     |  +-------------------+---------------+

3、decode(json->python)
1.以第三篇的登陆成功结果:{"success":true}为例,咱们其实最想知道的是success这个字段返回的是True仍是False
2.若是以content字节输出,返回的是一个字符串:{"success":true},这样获取后面那个结果就不方便了
3.若是通过json解码后,返回的就是一个字典:{u'success': True},这样获取后面那个结果,就用字典的方式去取值:result2["success"]

4.一样json数据转化成python可识别的数据,对应的表关系以下

     |  +---------------+-------------------+
     |  | JSON          | Python            |
     |  +===============+===================+
     |  | object        | dict              |
     |  +---------------+-------------------+
     |  | array         | list              |
     |  +---------------+-------------------+
     |  | string        | unicode           |
     |  +---------------+-------------------+
     |  | number (int)  | int, long         |
     |  +---------------+-------------------+
     |  | number (real) | float             |
     |  +---------------+-------------------+
     |  | true          | True              |
     |  +---------------+-------------------+
     |  | false         | False             |
     |  +---------------+-------------------+
     |  | null          | None              |
     |  +---------------+-------------------+

4、案例分析
1.好比打开快递网:http://www.kuaidi.com/,搜索某个单号,判断它的状态是否是已签收

2. 实现代码以下

5、参考代码:

# coding:utf-8
import requests
url = "http://www.kuaidi.com/index-ajaxselectcourierinfo-1202247993797-yunda.html"
headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"
           }  # get方法其它加个User-Agent就能够了
s = requests.session()
r = s.get(url, headers=headers,verify=False)
result = r.json()
data = result["data"]   # 获取data里面内容
print data
print data[0]         # 获取data里最上面的那个
get_result = data[0]['context'# 获取已签收状态
print get_result
if u"已签收" in get_result:
    print "快递单已签收成功"
else:
    print "未签收"

2.9 重定向Location

前言
某屌丝男A鼓起勇气向女神B打电话表白,女神B是个心机婊以为屌丝男A是好人,不想直接拒绝因而设置呼叫转移给闺蜜C了,最终屌丝男A和女神闺蜜C表白成功了,这种场景其实就是重定向了。
 
1、重定向
1. (Redirect)就是经过各类方法将各类网络请求从新定个方向转到其它位置,从地址A跳转到地址B了。
2.重定向状态码:
--301 redirect: 301 表明永久性转移(Permanently Moved)
--302 redirect: 302 表明暂时性转移(Temporarily Moved )

3.举个简单的场景案例,先登陆博客园打开个人博客首页,进个人随笔编辑界面,记住这个地址:https://i.cnblogs.com/EditPosts.aspx?opt=1
4.退出博客园登陆,把刚才个人随笔这个地址输入浏览器回车,抓包会看到这个请求状态码是302,浏览器地址栏瞬间刷新跳到登陆首页去了

 

 

2、禁止重定向(allow_redirects)
1.用get方法请求:https://i.cnblogs.com/EditPosts.aspx?opt=1
2.打印状态码是200,这是由于requets库自动处理了重定向请求了

3.自动处理重定向地址后,咱们就获取不到重定向后的url了,就没法走下一步,这里咱们能够设置一个参数禁止重定向:allow_redirects=False

(allow_redirects=True是启动重定向),而后就能够看到status_code是302了

3、获取重定向后地址
1.在第一个请求后,服务器会下发一个新的请求连接,在response的headers里,以下抓包:Location

2.用脚本去获取Location地址

4、参考代码:

# coding:utf-8
import requests
# 请求头
headers = {
     "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"
          }
s = requests.session()
# 打开个人随笔
r = s.get('https://i.cnblogs.com/EditPosts.aspx?opt=1',
          headers=headers,
          allow_redirects=True,
          verify=False)
# 打印状态码,自动处理重定向请求
print r.status_code
new_url = r.headers["Location"]
print new_url

2.10 参数关联

前言
咱们用自动化发帖以后,要想接着对这篇帖子操做,那就须要用参数关联了,发帖以后会有一个帖子的id,获取到这个id,继续操做传这个帖子id就能够了
 
1、删除草稿箱
1.咱们前面讲过登陆后保存草稿箱,那能够继续接着操做:删除刚才保存的草稿

2.用fiddler抓包,抓到删除帖子的请求,从抓包结果能够看出,传的json参数是postId

3.这个postId哪里来的呢?能够看上个请求url地址

4.也就是说保存草稿箱成功以后,重定向一个url地址,里面带有postId这个参数。那接下来咱们提取出来就能够了
 
2、提取参数
1.咱们须要的参数postId是在保存成功后url地址,这时候从url地址提出对应的参数值就好了,先获取保存成功后url

2.经过正则提取须要的字符串,这个参数值前面(postid=)和后面(&)字符串都是固定的
3.这里正则提出来的是list类型,取第一个值就能够是字符串了(注意:每次保存须要修改内容,不能重复)

三,传参
1.删除草稿箱的json参数传上面取到的参数:{"postId": postid[0]}

2.json数据类型post里面填json就行,会自动转json
3.接着前面的保存草稿箱操做,就能够删除成功了

4、参考代码

# coding:utf-8
import requests
url = "https://passport.cnblogs.com/user/signin"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
           "Accept": "application/json, text/javascript, */*; q=0.01",
           "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
           "Accept-Encoding": "gzip, deflate, br",
           "Content-Type": "application/json; charset=utf-8",
           "X-Requested-With": "XMLHttpRequest",
           "Content-Length": "385",
           "Cookie": "xxx已省略",
           "Connection": "keep-alive"
           }
payload = {
    "input1": "xxx",
    "input2": "xxx",
    "remember": True}
# 第一步:session登陆
s = requests.session()
r = s.post(url, json=payload, headers=headers, verify=False)
print r.json()
# 第二步:保存草稿
url2 = "https://i.cnblogs.com/EditPosts.aspx?opt=1"
body = {"__VIEWSTATE": "",
        "__VIEWSTATEGENERATOR": "FE27D343",
        "Editor$Edit$txbTitle": "这是个人标题:上海-悠悠",
        "Editor$Edit$EditorBody": "<p>这里是中文内容:http://www.cnblogs.com/yoyoketang/</p>",
        "Editor$Edit$Advanced$ckbPublished": "on",
        "Editor$Edit$Advanced$chkDisplayHomePage": "on",
        "Editor$Edit$Advanced$chkComments": "on",
        "Editor$Edit$Advanced$chkMainSyndication": "on",
        "Editor$Edit$lkbDraft": "存为草稿",
        }
r2 = s.post(url2, data=body, verify=False)
# 获取当前url地址
print r2.url
# 第三步:正则提取须要的参数值
import re
postid = re.findall(r"postid=(.+?)&", r2.url)
print postid  # 这里是list
# 提取为字符串
print postid[0]
# 第四步:删除草稿箱
url3 = "https://i.cnblogs.com/post/delete"
json3 = {"postId": postid[0]}
r3 = s.post(url3, json=json3, verify=False)
print r3.json()

2.11 token登陆

前言
有些登陆不是用cookie来验证的,是用token参数来判断是否登陆。
token传参有两种一种是放在请求头里,本质上是跟cookie是同样的,只是换个单词而已;另一种是在url请求参数里,这种更直观。
 
1、登陆返回token
1.以下图的这个登陆,无cookies

2.可是登陆成功后有返回token

2、请求头带token
1.登陆成功后继续操做其它页面,发现post请求的请求头,都会带token参数

2.这种请求其实比cookie更简单,直接把登陆后的token放到头部就行

3、token关联

1.用脚本实现登陆,获取token参数,获取后传参到请求头就能够了
2.若是登陆有验证码,前面的脚本登陆步骤就省略了,本身手动登陆后获取token

# coding:utf-8
import requests
header = {   # 登陆抓包获取的头部
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
        "Accept": "*/*",
        "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
        "Accept-Encoding": "gzip, deflate",
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "X-Requested-With": "XMLHttpRequest",
        "Content-Length": "423",
        "Connection": "keep-alive"
        }
body = {"key1": "value1",
        "key2": "value2"# 这里帐号密码就是抓包的数据
s = requests.session()
login_url = "http://xxx.login"   # 本身找带token网址
login_ret = s.post(login_url, headers=header, data=body)
# 这里token在返回的json里,能够直接提取
token = login_ret.json()["token"]
# 这是登陆后发的一个post请求
post_url = "http://xxx"
# 添加token到请求头
header["token"] = token
# 若是这个post请求的头部其它参数变了,也能够直接更新
header["Content-Length"]="9"
body1 = {
         "key": "value"
         }
post_ret = s.post(post_url, headers=header, data=body1)
print post_ret.content

2.12登陆案例分析(csrfToken)

前言:
有些网站的登陆方式跟前面讲的博客园cookies登陆和token登陆会不同,把csrfToken放到cookies里,登陆先后cookies是没有任何变化的,这种状况下如何绕过前端的验证码登陆呢?
 
1、登陆先后对比
1.若是登陆页面有图形验证码,这种咱们通常都是绕过登陆的方式,以下图经过抓包分析,首先不输入密码,抓包
(因为这个是别人公司内部网站,因此网址不能公开,仅提供解决问题的思路)

2.在登陆页面输入帐号和密码手动登陆后,抓包信息以下

 

3.抓包后cookies信息在登陆先后没任何变化,这里主要有三个参数:
--businessUsername:这个是帐号名称
--JSESSIONID: 这个是一串字符串,主要看这个会不会变(通常有有效期)copy出来就行
--csrfToken: 这个是一串字符串,主要看这个会不会变(通常有有效期)copy出来就行

2、get请求
1.像这种登陆方式的get请求,请求头部cookie没任何变化,这种能够直接忽略登陆,不用管登陆过程,直接发请求就行

2.代码实现

# coding:utf-8
import requests
# 优惠券列表
url = 'http://xxx/xxx/coupon/list'
h = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
"Accept-Encoding": "gzip, deflate",
"Cookie": "csrfToken=xxx(复制抓包的信息); JSESSIONID=xxx(复制抓包的信息); businessUsername=(用户名)",
"Connection": "keep-alive"
}
r = requests.get(url, headers=h)
print r.content

3、post请求遇到的坑
1.post请求其实也能够忽略登陆的过程,直接抓包把cookie里的三个参数(businessUsername、JSESSIONID、csrfToken)加到头部也是能够的。

2.可是这里遇到一个坑:用Composer发请求,重定向回到登陆页了

3.主要缘由:重定向的请求,cookie参数丢失了

4、重定向
1.解决上面问题,其实很简单,把重定向禁用(具体看2.8重定向Location这篇)后的连接获取到,从新发个get请求,头部带上cookies的三个参数就好了

# coding:utf-8
import requests
# 主要是post请求后重定向,cookie丢失,因此回到登陆页面了
# 解决办法,禁止重定向,获取重定向的url后,从新发重定向的url地址请求就好了
# 三个主要参数
csrfToken = '获取到的csrftoken,通常有有效期的'
jsessionId = '获取到的jsessionid'
userName = '用户名'
url = 'http://xxx/xxxx/update'
h1 = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
    "Accept-Encoding": "gzip, deflate",
    "Cookie": "csrfToken=%s; JSESSIONID=%s; businessUsername=%s" % (csrfToken, jsessionId, userName),
    "Connection": "keep-alive",
    "Content-Type": "application/x-www-form-urlencoded",
    "Content-Length": "115"
    }
body = {"instantMessageId":"56",
        "name": u"哈哈1",
        "order": "",
        "csrfToken": csrfToken,
        "type": "qq",
        "account": "1001"}
s = requests.session()
r1 = s.post(url, headers=h1, data=body, allow_redirects=False)
print r1.status_code
# 获取重定向的url地址
redirect_url = r1.headers["Location"]
print redirect_url
h2 = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0",
"Accept":
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
"Accept-Encoding": "gzip, deflate",
"Cookie": "csrfToken=%s; JSESSIONID=%s; businessUsername=%s" % (csrfToken, jsessionId, userName),
"Connection": "keep-alive"
}
r2 = s.get(redirect_url, headers=h2)
print r2.content
相关文章
相关标签/搜索