Python中Cookie的处理——Cookielib和Cookie

发布于 2022-03-01  546 次阅读


Cookie库

关于Cookie

  Cookie用于服务器实现会话,用户登录及相关功能时进行状态管理。要在用户浏览器上安装cookie,HTTP服务器向HTTP响应添加类似以下内容的HTTP报头:

Set-Cookie:session=8345234;expires=Sun,15-Nov-2013 15:00:00 GMT;path=/;domain=baidu.com
  • expires cookie的生存周期,path是cookie的有效路径,domain是cookie的有效域。
  • path 用于设置可以读取一个cookie的最顶层的目录。将cookie的路径设置为你的网页最顶层的目录可以让该该目录下的所有网页都能访问该cookie。
  • domain 有些网站有许多小的域名,例如百度可能还在"news.baidu.com" "zhidao.baidu.com" 和"v.baidu.com" 域名下有网页。如果想让"baidu.com"下的所有机器都可以读取该cookie,必须在cookie中加入 "domain=.baidu.com" 。
  • 用户浏览器会存储Cookie直到过期,浏览器会向符合path和domain的服务器发送类似以下内容的HTTP请求报头:Cookie:session=8345234
  • 浏览器将cookie发送回HTTP服务器时,使用key=value字符串的编码形式,不返回expires,path和domain等可选属性。

  cookie字符串通常位于HTTP_COOKIE环境变量中,通过以下代码可以读取:

import os
print "Content-type: text/plain\n"
if "HTTP_COOKIE" in os.environ:
    print os.environ["HTTP_COOKIE"]
else:
    print "HTTP_COOKIE not set!"

Cookie库简介

  Python中Cookie模块(python3中为http.cookies)提供了一个类似字典的特殊对象SimpleCookie,其中存储并管理着称为Morsel的cookie值集合,每个Morsel都有name,value以及可选属性(expires,path,domain,comment,max-age,secure,version,httponly)。
  SimpleCookie可使用output()方法创建以HTTP报头形式表示的cookie数据输出,用js_output()方法生成包含javascript代码的字符串。

Cookie库的简单使用

用HTTP_COOKIE生成cookie

cookie=Cookie.SimpleCookie(os.environ['HTTP_COOKIE'])
print cookie.output()

set cookie:

import Cookie
import datetime
import random

expiration = datetime.datetime.now() + datetime.timedelta(days=30)
cookie = Cookie.SimpleCookie()
cookie["session"] = random.randint(1,1000000000)
cookie["session"]["domain"] = ".baidu.com"
cookie["session"]["path"] = "/"
cookie["session"]["expires"] = expiration.strftime("%a, %d-%b-%Y %H:%M:%S PST")

print "Content-type: text/plain"
print cookie.output()
print
print "Cookie set with: " + cookie.output()

Cookielib库

Cookielib库简介

  Python中cookielib库(python3中为http.cookiejar)为存储和管理cookie提供客户端支持。该模块主要功能是提供可存储cookie的对象。使用此模块捕获cookie并在后续连接请求时重新发送,还可以用来处理包含cookie数据的文件。这个模块主要提供了这几个对象:CookieJarFileCookieJarMozillaCookieJarLWPCookieJar

Cookielib库中主要对象

CookieJar——CookieJar对象存储在内存中

# 捕获Cookie
import urllib2
import cookielib

cookie=cookielib.CookieJar()
handler=urllib2.HTTPCookieProcessor(cookie)
opener=urllib2.build_opener(handler)
opener.open('http://www.google.com.hk')

print(cookie)

  所捕获的对象为Cookie实例的集合,Cookie实例有name,value,path,expires等属性,通过以下操作可以进行查看:

for ck in cookie:
    print ck.name,':',ck.value

将cookie捕捉到文件——FileCookieJar对象

  FileCookieJar实现了save()load()revert()三个函数。但在FileCookieJar的源码中FileCookeJar并没有实现save()的具体功能,而是直接抛出了NotImplementedError

def save(self, filename=None, ignore_discard=False, ignore_expires=False):
    """Save cookies to a file."""
    raise NotImplementedError()

  而FileCookieJar的子类MozillaCookieJarLWPCookieJar实现了save()方法。

对象名称 含义
FileCookieJar(filename) 创建FileCookieJar实例,检索cookie信息并将信息存储到文件中,filename是文件名。
MozillaCookieJar(filename) 创建与Mozilla cookies.txt文件兼容的FileCookieJar实例。
LWPCookieJar(filename) 创建与libwww-perl Set-Cookie3文件兼容的FileCookieJar实例。

示例代码:

import cookielib
import urllib2

cookies = cookielib.MozillaCookieJar()
cookieHandler = urllib2.HTTPCookieProcessor(cookiejar=cookies)
opener = urllib2.build_opener(cookieHandler)
urllib2.install_opener(opener)

request = urllib2.Request("http://www.baidu.com")
urllib2.urlopen(request)

# 将cookie存为一个文件
cookies.save(filename="cookie.txt")

# 新建一个cookie对象
cookies2 = cookielib.MozillaCookieJar()

# 从文件中读取cookie
cookies2.load('cookie.txt')
for cookie in cookies2:
    print cookie.name, cookie.value

  save()函数带有两个参数,ignore_discardignore_expires

  • ignore_discard: save even cookies set to be discarded. 即也保存需要被丢弃的cookie

  • ignore_expires: save even cookies that have expired. 即过期的cookie也保存。

  revert()函数的作用是Clear all cookies and reload cookies from a saved file——清除所有Cookie并从保存Cookie的文件中重新加载。

urllib2的HTTPCookieProcessor

  在调用urllib2.urlopen(url)的时候,其实urllib2open函数内部创建了一个默认的opener对象。然后调用opener.open()函数。但是默认的opener并不支持cookie。而支持cookie的opener,在urllib2中使用的是HTTPCookieProcessor
  示例:

import cookielib
import urllib2

cookies = cookielib.CookieJar()
cookieHandler = urllib2.HTTPCookieProcessor(cookiejar=cookies)
opener = urllib2.build_opener(cookieHandler)
urllib2.install_opener(opener)

request = urllib2.Request("http://www.baidu.com")
urllib2.urlopen(request)
for cookie in cookies:
    print cookie.name, cookie.value

  上面的代码表示urllib2可以将Cookie从response从提取出来。

python3 requests和http.cookiejar有关cookie的使用

结合urllib使用

  cookielib模块一般与urllib模块配合使用,主要用在urllib.requests.build_oper()函数中作为urllib.requests.HTTPCookieProcessor()的参数。

import urllib.request
import http.cookiejar

# 初始化一个CookieJar来处理Cookie
cookie=http.cookiejar.CookieJar()

#实例化一个全局opener
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)

# 获取cookie
r=opener.open('https://www.hao123.com/')

# 访问主页 自动带着cookie信息
result = opener.open('https://www.hao123.com/')
print (cookie)
# print (result.read())

Requests中cookie的使用

  对于cookies格式的转化,提供了三个工具方法:

  • requests.utils.dict_from_cookiejar(cj)

  • requests.utils.cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True)

  • requests.utils.add_dict_to_cookiejar(cj, cookie_dict)

# 工具方法:requests.cookies.RequestsCookieJar转换成字典
load_cookies = requests.utils.dict_from_cookiejar(r.cookies)

# 工具方法将字典转换成RequestsCookieJar,赋值给session的cookies
requests.utils.cookiejar_from_dict({c.name: c.value for c in r.cookies})
requests.session.cookies=requests.utils.cookiejar_from_dict(load_cookies)

  获取的cookies,可以用keys()和values()看内容,但本身不是字典格式,以下可以打印出字典方式查看

r=requests.get('https://www.hao123.com/',cookies=load_cookies)

print ({c.name: c.value for c in r.cookies})

requests.session()

  requests中的session对象能够让我们跨http请求保持某些参数,即让同一个session对象发送的请求头携带某个指定的参数。

import requests

s = requests.session()
# 第一步:发送一个请求,用于设置请求中的cookies
cookies = dict(cookies_are='cookie1')
# tips: http://httpbin.org能够用于测试http请求和响应
r1 = s.get(url='http://httpbin.org/cookies', cookies=cookies)
print(r1.text)
# 第二步:发送一个请求,用于再次设置请求中的cookies
cookies = dict(cookies_are='cookie2')
r2 = s.get(url='http://httpbin.org/cookies', cookies=cookies)
print(r2.text)

# 输出
# {
#   "cookies": {
#     "cookies_are": "cookie1"
#   }
# }
# 
# {
#   "cookies": {
#     "cookies_are": "cookie2"
#   }
# }

requests.cookies.RequestsCookieJar()

import requests

jar = requests.cookies.RequestsCookieJar()
jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
url = 'http://httpbin.org/cookies'
r = requests.get(url, cookies=jar)
print(r.text)

requests.utils.dict_from_cookiejar()

import requests

def login():
    login_url = 'http://www.xxx.com/login'
    headers = {
        "Accept": "application/json, text/javascript, */*; q=0.01"
    }
    body = {
        "usercode": "liuzz05@****.com",
        "password": "123456"
    }
    try:
        res = requests.post(url=login_url, headers=headers, data=body)
        cookies = res.cookies

        cookie = requests.utils.dict_from_cookiejar(cookies)

        return cookie
    except Exception as err:
        print('获取cookie失败:\n{0}'.format(err))

def get_data():
    cookie = login()
    res = requests.get(url=get_data_url, cookies=cookie)
    print(res.text)

requests.utils.cookiejar_from_dict()

import requests

def login():
    login_url = 'http://www.xxx.com/login'
    headers = {
        "Accept": "application/json, text/javascript, */*; q=0.01"
    }
    body = {
        "usercode": "liuzz05@****.com",
        "password": "123456"
    }
    try:
        res = requests.post(url=login_url, headers=headers, data=body)
        cookies = res.cookies.items()

        cookie = ''
        for name, value in cookies:
            cookie += '{0}={1};'.format(name, value)
        # 或使用下面的代码
        # requests.utils.cookiejar_from_dict({c.name: c.value for c in cookies})

        return cookie
    except Exception as err:
        print('获取cookie失败:\n{0}'.format(err))

def get_data():
    cookie = login()
    headers = {
        "cookie": cookie
    }
    res = requests.get(url=get_data_url, headers=headers)
    print(res.text)

html.parser库

  这个模块定义了一个HTMLParser类,为HTML(超文本标记语言)和XHTML文本文件解析提供基础。

class html.parser.HTMLParser( * , convert_charrefs = True)
  1. HTMLParser主要是用来解析HTML文件(包括HTML中无效的标记)
  2. 参数convert_charrefs表示是否将所有的字符引用自动转化为Unicode形式,Python3.5以后默认是True
  3. HTMLParser可以接收相应的HTML内容,并进行解析,遇到HTML的标签会自动调用相应的handler(处理方法)来处理,用户需要自己创建相应的子类来继承HTMLParser,并且复写相应的handler方法,具体方法在下文中
  4. HTMLParser不会检查开始标签和结束标签是否是一对

html.parser.HTMLParser

  • HTMLParser.feed(data)

  接收一个字符串类型的HTML内容,并进行解析。如果包含完整的元素,则被处理;如果数据不完整,将被缓冲直到更多的数据被填充,或者close()被调用。data必须为str类型。

  • HTMLParser.close()

  当遇到文件结束标签后进行的处理方法,强制处理所有缓冲数据。这个方法能被派生类重新定义,用于在输入的末尾定义附加处理,但是重定义的版本应当始终调用基类HTMLParserclose()方法。

  • HTMLParser.reset()

  重置实例。丢失所有未处理的数据。在实例化阶段被隐式调用。

  • HTMLParser.getpos()

  返回当前行号和偏移值。

  • HTMLParser.get_starttag_text()

  返回最近打开的开始标记中的文本。 结构化处理时通常应该不需要这个,但在处理"已部署"的HTML或是在以最小改变来重新生成输入时可能会有用处(例如可以保留属性间的空格等)。

  • HTMLParser.handle_starttag(tag, attrs)

  这个方法在标签开始的时候被调用。例如<div id="main">,tag参数是小写的标记名,指的是div,attrs参数是一个(name,Value)的列表,包含了所有在标记的<>括号中找到的属性。name转换为小写,value的引号被去除,字符和实体引用都会被替换。

  • HTMLParser.handle_startendtag(tag, attrs)

  类似于handle_starttag(),只是在解析器遇到 XHTML 样式的空标记时被调用(<img ... />)。这个方法能被需要这种特殊词法信息的子类重载;默认实现仅简单调用handle_starttag()handle_endtag()

  • HTMLParser.handle_comment(data)

  对HTML中注释的处理方法。

  • HTMLParser.handle_endtag(tag)

  对结束标签的处理方法。例如</div>,参数tag指的是div,即小写的标签名。

  • HTMLParser.handle_data(data)

  对标签之间的数据的处理方法。<tag>test</tag>,data指的是“test”。

  • HTMLParser.handle_entityref(name)

  这个方法被用于处理&name; 形式的命名字符引用(例如 >),其中name是通用的实体引用(例如: 'gt')。如果convert_charrefsTrue,该方法永远不会被调用。

  • HTMLParser.handle_charref(name)

  这个方法被用来处理&#NNN;&#xNNN;形式的十进制和十六进制字符引用。例如,>等效的十进制形式为>,而十六进制形式为&#x3E;在这种情况下,方法将收到 '62''x3E' 。如果convert_charrefs为True,则该方法永远不会被调用。

  • HTMLParser.handle_decl(decl)

  这个方法用来处理"HTML doctype"申明(例如<!DOCTYPE html>),decl形参为<!...>标记中的所有内容(例如:'DOCTYPE html')

  • HTMLParser.handle_pi(data)

  此方法在遇到处理指令的时候被调用。data形参将包含整个处理指令。例如,对于处理指令<?proc color='red'>,这个方法将以handle_pi("proc color='red'")形式被调用。它旨在被派生类重载;基类实现中无任何实际操作。