背景:

接口访问后返回的cookies,需要保存在文本中,然后其他接口请求时直接去读取文本中的内容。问题在于转储cookies时出现同一字段内容丢失的情况;

cookies内容查看(CSDN为例):

Request Cookies:

Response Cookies

同上两套图可以看出:Cookie的内容很丰富,有很多属性,有name、value、domain、path等特征。不同的域不同的路径下可以存在同样名字的cookie。也就是说同一个请求或返回不会存在所有字段都一样的内容的cookie。当让我们一般的请求里,只会设置cookie的name和value,所以在这种意识下处理cookie会导致一些数据丢失。

cookies的字段说明:

属性 描述
name Cookie的名称,Cookie一旦创建,名称便不可更改
value Cookie的值。如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码
expires/maxAge Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为-1。
secure 该Cookie是否仅被使用安全协议传输。安全协议。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。
path Cookie的使用路径。如果设置为“/sessionWeb/”,则只有contextPath为“/sessionWeb”的程序可以访问该Cookie。如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/”。
domain 可以访问该Cookie的域名。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.”。
comment 该Cookie的用处说明,浏览器显示Cookie信息的时候显示该说明。
version Cookie使用的版本号。0表示遵循Netscape的Cookie规范,1表示遵循W3C的RFC 2109规范

由上面的表我们大致的了解下字段的含义啊,可能一些字段没有点出来,但是够用了,上图中有http,应该是http-only。用不上也就暂时不管了。

应用:python+requests去处理接口--cookies(防止丢失)

# !/usr/bin/env python
# -*-coding:utf-8-*-

import requests,json

def renren_login():
    url='http://'
    data = {}
    headers = {}
    r = requests.post(url=url, headers=headers, data=data)
    cookies_file=requests.utils.dict_from_cookiejar(r.cookies)    # 将cookiejar转化为字典
    json.dump(cookies_file,open('renren_cookies','w'))            #  用json.dump写到文件中
    return r.cookies

def up_files():
    url=''
    data = {}
    headers = {}
    files={'file':('1.jpg',open('C:\\1.jpg','rb'),'image/jpeg')}
    cookies=json.load(open('renren_cookies','r'))    # 读取文件中的cookies
    # 此处有个问题:"dict转为cookiesjar时候,cookie中有个字段是重复的,因此字典中就少了一个key值"
  dict_cookiesjar=requests.utils.cookiejar_from_dict(cookies,cookiejar=None,overwrite=True)
    r = requests.post(url=url,headers=headers,data=data,cookies=cookies,files=files)
    print(r.text)

up_files()

分析一下:dict_from_cookiejar方法去转存cookie的时候,他只保留了name和value,其他的字段没有考虑在内,所以原来同名的cookie会被去重,那么我们想要保存cookie到文件里怎么办?那么就重新设计一种方式去存,因为我们现在知道cookie都有哪些字段了,我们需要什么,我们就存什么,上示例:

# !/usr/bin/env python
# -*-coding:utf-8-*-

import requests,json
from requests.cookies import RequestsCookieJar,create_cookie

# 方法有很多,可以选择把requests.utils.dict_from_cookiejar方法重写一下 改成list,
# 要点是要保证数据的唯一性,list可重复,还有就是每一位都是一个tuple,
def list_from_cookiejar(cj):
    cookie_list = list()
    for cookie in cj:
        # 可以根据需求去保存cookie的特征值
        cookie_list.append((cookie.name, cookie.value, cookie.path))   
    return cookie_list

# 去加载文件中list,核心代码是create_cookie:回给人多cookie对象的参数去实例化
def reload_cookie_from_file(cookiejar=None, overwrite=True):
    if cookiejar is None:
        cookiejar = RequestsCookieJar()
    names_from_jar = [cookie.name for cookie in cookiejar]
    with open("cookie_file", "r+") as cf:
        for c_ in cf:
            c_ = str(c_).strip().split("=")
            if overwrite or (c_[0] not in names_from_jar):
                # 根据保存的重新读取 并实例化为cookie
                cookiejar.set_cookie(create_cookie(c_[0], c_[1], path=c_[2]))   
    return cookiejar

# 把接口获取的cookies转化为list,保存到文件中
def renren_login_for_dump():
    url=''
    data = {}
    headers = {}
    r = requests.post(url=url, headers=headers, data=data)
    cookies_file=list_from_cookiejar(r.cookies)  #将cookiejar转化为二位数组
    print cookies_file
    with open("cookie_file", "w+") as cf:
        for c in cookies_file:
            cf.write(str(c[0]+"="+c[1]+"="+ c[2]) + "\n")
        cf.flush()
    # return r.cookies

# 直接调用方法就可以使用了,没必要使用json去dump和reload
def up_files_with_cookie():
    url=''
    data = {}
    headers = {}
    files={'file':('1.jpg',open('C:\\1.jpg','rb'),'image/jpeg')}
    cookies=reload_cookie_from_file()
    r = requests.post(url=url,headers=headers,data=data,cookies=cookies,files=files)
    print(r.text)


# print reload_cookie_from_file()
up_files_with_cookie()

总结:

1.对操作的对象要有特征上的认识;

2.一些问题一般都在官方文档和源码里给出了,需要去探索和发现;