发布时间:2025-12-09 21:39:30 浏览次数:4
首先,推荐几个帖子,大伙可以先看看。国内通过cookiejar主要获取cookie的方法,大致都是如此的。
http.cookiejar库之CookieJar_pigYanYan的博客-CSDN博客
Python编程:cookiejar的使用_彭世瑜的博客-CSDN博客
再推荐一个资料帖,这个帖子主要涉及后面介绍的一种获取cookie的过程中所使用的一个方法。
cookielib_网络 | Internet_Python_参考手册_非常教程
本此,之所以写这个贴子主要是记录下,国外通过cookiejar是如何获取cookie的。总的来说,要比国内搞得复杂的多,但是也底层的多。
import gzip, osfrom http import cookiejarfrom urllib.request import Requestfrom xmlrpc.client import TransportBUGZILLA_COOKIE_FILE = '/tmp/.bugzilla-cookies.txt'class CookieTransport(Transport):"""A subclass of xmlrpclib.Transport that supports cookies."""cookiejar = Nonedef __init__(self, use_datetime=0, url=None):"""Extend xmlrpclib.Transport's constructor to include url"""self.url = urlsuper(CookieTransport, self).__init__(use_datetime=use_datetime)def send_cookies(self, connection, cookie_request):"""Send cookies to Bugzilla server"""if self.cookiejar is None:# 实例化 MozillaCookieJar,这里国内外用法一致# BUGZILLA_COOKIE_FILE是用来存储具体的cookie信息的文件self.cookiejar = cookiejar.MozillaCookieJar(BUGZILLA_COOKIE_FILE)if os.path.exists(BUGZILLA_COOKIE_FILE):# 再次运行的时候,就可以直接读取cookie信息了self.cookiejar.load(BUGZILLA_COOKIE_FILE)else:# 初次运行,文件BUGZILLA_COOKIE_FILE是不存在的,所以save一把,用于创建文件self.cookiejar.save(BUGZILLA_COOKIE_FILE)# 将cookie信息从MozillaCookieJar对象中提取出来,添加到 cookie_request 对象的header里去# cookie_request对象就是 urllib.request.Request 对象,如果,有先看国内搞cookie的那几个# 帖子,就应该知道,用国内的方法,只需传入 urllib.request.Request 对象,去实际访问服务器的时候# 就可以直接获取到 cookie 信息了。而其具体实现的过程,就包括了下面的这个步骤,这里相当与将国内# 介绍的一体化操作,又分解了# 这里注意,初次运行代码到这里的时候,是不会添加啥东西出来的,因为这个时候,MozillaCookieJar# 对象此时还没有获取到cookie信息呢,只有再次运行到此处的时候,代码执行 self.cookiejar.load(BUGZILLA_COOKIE_FILE)# 动作的时候,self.cookiejar中才会存在具体的cookie信息,然后才能将其添加到cookie_request(即urllib.request.Request)# 对象的header中self.cookiejar.add_cookie_header(cookie_request)# 从 urllib.request.Request 对象中提取cookie信息cookielist = list()for header, headerdata in cookie_request.header_items():if header.startswith('Cookie'):cookielist.append([header, headerdata])# 将cookie添加到connection对象for header, headerdata in cookielist:connection.putheader(header, headerdata)def single_request_with_cookies(self, host, handler, request_body, verbose=False):# 首先一样是先造一个Request对象(其作用本身就是用于存储一些信息的,比如:url,header等)request_url = "https://%s%s" % (host, handler)cookie_request = Request(request_url)# 然后造一个发送请求的对象, 本来按照如下方法正常创造即可,但是,# 由于我们后续需要对header添加cookie,所以就不能如此使用了,python2.7版本可以这样用# 但是3.8版本是完全不行了,3.8版本对send_request方法做出了高度的集成改动,总体来说# 可以更加方便的创建可以发送请求的connect对象了,但是同样降低了其使用的灵活性,就比如# 给connect对象添加cookie,就会变得无法实现# h = self.send_request(host, handler, request_body, debug=verbose)# 这里我将python3.8版本里的 send_request 函数里的内容直接从xmlrpc库提取出来,直接用# 注意具体的使用会和send_request中略有不同,send_request方法的原始内容,我放到下面了h = self.make_connection(host)headers = self._headers + self._extra_headersif verbose:h.set_debuglevel(1)if self.accept_gzip_encoding and gzip:h.putrequest("POST", handler, skip_accept_encoding=True)headers.append(("Accept-Encoding", "gzip"))else:h.putrequest("POST", handler)headers.append(("Content-Type", "text/xml"))headers.append(("User-Agent", self.user_agent))self.send_headers(h, headers)# 注意,要修改header的内容,必须要在send_content动作之前# 这里就是添加cookie到header的地方, 也是实例化 MozillaCookieJar 对象的地方self.send_cookies(h, cookie_request)# 将request_body发送到服务器self.send_content(h, request_body)# 获取来自服务器的相应,而这个相应中,就蕴含着cookie信息response = h.getresponse()# 这个类是有必要造的,因为后续从response中提取cookie的时候,需要这样一种# 数据结构class CookieResponse:"""parse headers and get cookies herefake a response object that we can fill with the headers above"""def __init__(self, headers):self.headers = headersdef info(self):return self.headers# 构建extract_cookies所需的参数cookie_response = CookieResponse(response.msg)# 从response中提取cookie信息# 正如上面send_cookies方法的注释中所提到的,这是将一体化动作拆分的过程。# cookie_request对象起一定的校验功能。另外就是,原本在一体化执行的过程,所有# 调用过程均存在于内部,外部仅需传入一个urllib.request.Request对象,所以# 此处在模仿内部调用的过程,就肯定也需要构造一个同样的对象,供其使用,因此在我# 看来,extract_cookies方法的重头戏就是从response提取cookie,传入cookie_request# 的目的更像是打个辅助罢了self.cookiejar.extract_cookies(cookie_response, cookie_request)# 将提取到的cookie信息,保存到文件中self.cookiejar.save(self.cookiejar.filename)if response.status == 200:self.verbose = verbosereturn self.parse_response(response)def send_request(self, host, handler, request_body, debug):"""xmlrpc.client.Transport.send_request()的原始内容"""connection = self.make_connection(host)headers = self._headers + self._extra_headersif debug:connection.set_debuglevel(1)if self.accept_gzip_encoding and gzip:connection.putrequest("POST", handler, skip_accept_encoding=True)headers.append(("Accept-Encoding", "gzip"))else:connection.putrequest("POST", handler)headers.append(("Content-Type", "text/xml"))headers.append(("User-Agent", self.user_agent))self.send_headers(connection, headers)self.send_content(connection, request_body)注意,上述内容,为演示,说明内容,并不是说,照搬可以完整执行哈。
关于 def send_cookies(self, connection, cookie_request): 方法做一个演示:
在执行 self.cookiejar.add_cookie_header(cookie_request) 之前,cookie_request 对象长这样:
执行之后,长这样:
这不是果断加进header了。
另外,关于 self.cookiejar.save(self.cookiejar.filename) 保存cookie信息到文件,也介绍一个:
执行保存动作之前,.bugzilla-cookies.txt 文件长这样:
之后: