RPC(Remote Procedure Call Protocol)是远程过程调用协议,一种不同于http协议的用于构建分布式系统。python提供xmlrpc库,下面是py2和py3的client类,可以带cookie请求数据。Show you the code:
python2
class CookieTransportRequest:
"""A Transport request method that retains cookies over its lifetime.
The regular xmlrpclib transports ignore cookies. Which causes
a bit of a problem when you need a cookie-based login, as with
the XPLAN XMLRPC EDAI interface.
So this is a helper for defining a Transport which looks for
cookies being set in responses and saves them to add to all future
requests.
"""
def __init__(self, use_datetime=0):
self._use_datetime = use_datetime
self._connection = (None, None)
self._extra_headers = []
self.cookies = {}
def extract_cookies(self, response): # 生成cookie,具体根据应用rpc修改
for header in response.msg.getallmatchingheaders("Set-Cookie"):
val = header.split(':', 1)[1].strip()
cookie = val.split(';', 1)[0].strip()
cookiePair = cookie.split('=', 1)
self.cookies[cookiePair[0].strip()] = cookiePair[1].strip()
def get_cookies_header(self):
cookieStr = ''
for cookieName in self.cookies.keys():
cookieStr = cookieStr + '%s=%s' % (cookieName, self.cookies[cookieName])
return cookieStr
def send_cookies(self, connection):
cookieStr = ''
for cookieName in self.cookies.keys():
cookieStr = cookieStr + '%s=%s' % (cookieName, self.cookies[cookieName])
if cookieStr != '':
connection.putheader("Cookie", cookieStr)
def login(self, host, homeUri, authUri, authBody, verbose=0):
headers = {}
self.verbose = verbose
conn = self.make_connection(host)
if verbose:
conn.set_debuglevel(1)
conn.request('GET', homeUri)
try:
response = conn.getresponse()
except AttributeError:
response = conn._conn.getresponse()
self.extract_cookies(response) ##生成一个self.cookie
response.read() # 生成页面
if response.status in (404,500,503,505,501):
raise xmlrpclib.ProtocolError(host + homeUri, response.status,
response.reason, response.msg.headers)
#判断页面状态
headers.clear()
headers = {"Content-Type": "application/x-www-form-urlencoded","Accept": "text/plain","Connection":"keep-alive"}
headers['Cookie'] = self.get_cookies_header()
conn.request('POST', authUri, authBody, headers) ##进行登录
try:
response = conn.getresponse()
except AttributeError:
response = conn._conn.getresponse()
self.extract_cookies(response)
response.read()
if response.status in (403,404,401,500,503,505,501):
raise xmlrpclib.ProtocolError(host + homeUri, response.status,
'Authenticate error', response.msg.headers)
headers.clear()
headers['Cookie'] = self.get_cookies_header() ##在header中加入cookie
conn.request('GET', homeUri, None, headers) ##请求这页面传入 cookie 与 header
try:
response = conn.getresponse()
except AttributeError:
response = conn._conn.getresponse()
self.extract_cookies(response) ##再次获取cookie
response.read()
def request(self, host, handler, request_body, verbose=0):
self.verbose = verbose
# issue XML-RPC request
h = self.make_connection(host)
if verbose:
h.set_debuglevel(1)
self.send_request(h, handler, request_body)
self.send_host(h, host)
self.send_cookies(h)
self.send_user_agent(h)
self.send_content(h, request_body)
# Deal with differences between Python 2.4-2.6 and 2.7.
# In the former h is a HTTP(S). In the latter it's a
# HTTP(S)Connection. Luckily, the 2.4-2.6 implementation of
# HTTP(S) has an underlying HTTP(S)Connection, so extract
# that and use it.
try:
response = h.getresponse()
except AttributeError:
response = h._conn.getresponse()
# Add any cookie definitions to our list.
self.extract_cookies(response)
if response.status != 200:
raise xmlrpclib.ProtocolError(host + handler, response.status,
response.reason, response.msg.headers)
# if response.info().get('Content-Encoding') == 'gzip':
# buf = StringIO(response.read())
# f = gzip.GzipFile(fileobj=buf)
# data = f.read()
# else:
# data = response.read()
data = response.read()
parser, unmarshaller = self.getparser()
# import re, pickle
# data = re.sub(u"[\x00-\x08\x0b-\x0c\x0e-\x1f]+", u"", data)
# data = re.sub(u"[\n]+", u"", data)
# print('\n', "re after:", data)
# data = xmlrpclib.Binary(pickle.dumps(data)).data
# import chardet
# print chardet.detect(data)
parser.feed(data)
parser.close()
return unmarshaller.close()
class CookieTransport(CookieTransportRequest, xmlrpclib.Transport):
pass
class SafeCookieTransport(CookieTransportRequest, xmlrpclib.SafeTransport):
pass
def getCookie():
cookie = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
AUTHBODY = urllib.urlencode(AUTHDATA)
req = urllib2.Request(url='http://' + HOST + HOMEURL)
opener.open(req)
cookistr = ''
for item in cookie:
cookistr = cookistr + '%s=%s' % (item.name, item.value)
headers = {}
headers.clear()
headers = {'Content-type': 'application/x-www-form-urlencoded', "Accept": "text/plain", "Connection": "keep-alive"}
headers['Cookie'] = cookistr
loginpage = urllib2.Request(url='http://' + HOST + AUTHURL, data=AUTHBODY, headers=headers)
opener.open(loginpage)
cookistr = ''
for item in cookie:
cookistr = cookistr + '%s=%s' % (item.name, item.value)
headers = {}
headers.clear()
headers = {'Content-type': 'application/x-www-form-urlencoded', "Accept": "text/plain", "Connection": "keep-alive"}
headers['Cookie'] = cookistr
return headers
python3
class CookieTransportRequest:
"""A Transport request method that retains cookies over its lifetime.
The regular xmlrpclib transports ignore cookies. Which causes
a bit of a problem when you need a cookie-based login, as with
the XPLAN XMLRPC EDAI interface.
So this is a helper for defining a Transport which looks for
cookies being set in responses and saves them to add to all future
requests.
"""
def __init__(self, use_datetime=0, use_builtin_types=False):
self._use_datetime = use_datetime
self._use_builtin_types = use_builtin_types
self._connection = (None, None)
self._extra_headers = []
self.cookies = []
def extract_cookies(self, response):
print(response.msg.getallmatchingheaders("Set-Cookie"))
print(response.msg.get_all("Set-Cookie")) # 与py2的区别
if not response.msg.getallmatchingheaders("Set-Cookie") and not response.msg.get_all("Set-Cookie"):
print("\n extract_cookies", self.cookies)
return self.cookies
else:
cookie_info = response.msg.get_all("Set-Cookie")
if "SERVERID" in cookie_info[0]:
return self.cookies
self.cookies = []
for header in cookie_info:
self.cookies.append(header.split(";", 1)[0])
print("\n extract_cookies", self.cookies)
return self.cookies
def get_cookies_header(self):
cookieStr = ''
for cookieName in self.cookies:
cookieStr = cookieStr + '%s=%s' % (cookieName.split('=', 1)[0], cookieName.split('=', 1)[1])
print("get_cookies", cookieStr)
return cookieStr
def send_headers(self, connection, headers):
for key, val in headers:
connection.putheader(key, val)
def send_request(self, host, handler, request_body, debug):
connection = self.make_connection(host)
extra_headers = self._extra_headers[:]
print("\nextra_headers", extra_headers)
if extra_headers:
if isinstance(extra_headers, dict):
extra_headers = extra_headers.items()
print("\nextra_headers", extra_headers)
for key, value in extra_headers:
connection.putheader(key, value)
if debug:
connection.set_debuglevel(1)
if self.accept_gzip_encoding and gzip:
connection.putrequest("POST", handler, skip_accept_encoding=True)
extra_headers.append(("Accept-Encoding", "gzip"))
else:
connection.putrequest("POST", handler)
extra_headers.append(("Cookie", self.get_cookies_header()))
extra_headers.append(("User-Agent", self.user_agent))
extra_headers.append(("Content-Type", "text/xml"))
self.send_headers(connection, extra_headers)
self.send_content(connection, request_body)
return connection
def login(self, host, homeUri, authUri, authBody, verbose=0):
headers = {}
conn = self.make_connection(host)
if verbose:
conn.set_debuglevel(1)
conn.request('GET', homeUri)
try:
response = conn.getresponse()
except AttributeError:
response = conn._conn.getresponse()
self.extract_cookies(response) ##生成一个self.cookies
response.read() # 生成页面
print(response.status)
if response.status in (404,500,503,505,501):
raise xmlrpc.client.ProtocolError(host + homeUri, response.status,
response.reason, response.msg.headers)
#判断页面状态
headers.clear()
headers = {"Content-Type": "application/x-www-form-urlencoded","Accept": "text/plain","Connection":"keep-alive"}
headers['Cookie'] = self.get_cookies_header()
print(headers)
conn.request('POST', authUri, authBody, headers) ##进行登录
try:
response = conn.getresponse()
except AttributeError:
response = conn._conn.getresponse()
self.extract_cookies(response)
response.read()
print(response.status)
if response.status in (403,404,401,500,503,505,501):
raise xmlrpc.client.ProtocolError(host + homeUri, response.status,
'Authenticate error', response.msg.headers)
headers.clear()
headers['Cookie'] = self.get_cookies_header() ##在header中加入cookie
print(headers)
conn.request('GET', homeUri, None, headers) ##请求这页面传入 cookie 与 header
try:
response = conn.getresponse()
except AttributeError:
response = conn._conn.getresponse()
self.extract_cookies(response) ##再次获取cookie
response.read()
print("\nagain get", response.status)
def request(self, host, handler, request_body, verbose=1):
# issue XML-RPC request
print(host, handler, request_body, self.cookies)
# h = self.make_connection(host)
# if verbose:
# h.set_debuglevel(1)
h = self.send_request(host, handler, request_body, verbose)
# Deal with differences between Python 2.4-2.6 and 2.7.
# In the former h is a HTTP(S). In the latter it's a
# HTTP(S)Connection. Luckily, the 2.4-2.6 implementation of
# HTTP(S) has an underlying HTTP(S)Connection, so extract
# that and use it.
try:
response = h.getresponse()
except AttributeError:
response = h._conn.getresponse()
# Add any cookie definitions to our list.
# self.extract_cookies(response)
if response.status != 200:
raise xmlrpc.client.ProtocolError(host + handler, response.status,
response.reason, response.msg.headers)
# if response.info().get('Content-Encoding') == 'gzip':
# buf = StringIO(response.read())
# f = gzip.GzipFile(fileobj=buf)
# data = f.read()
# else:
# data = response.read()
data = response.read().decode('utf-8')
parser, unmarshaller = self.getparser()
if not data:
return parser.close()
if verbose:
print("body:", repr(data))
# import re, pickle
# data = re.sub(u"[\x00-\x08\x0b-\x0c\x0e-\x1f]+", u"", data)
# data = re.sub(u"[\n]+", u"", data)
# print('\n', "re after:", data)
# data = xmlrpc.client.Binary(pickle.dumps(data)).data
# import chardet
# print chardet.detect(data)
parser.feed(data)
parser.close()
return unmarshaller.close()
class CookieTransport(CookieTransportRequest, xmlrpc.client.Transport):
pass
class SafeCookieTransport(CookieTransportRequest, xmlrpc.client.SafeTransport):
pass
def getCookie():
cookie = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookie))
AUTHBODY = urllib.parse.urlencode(AUTHDATA).encode(encoding='UTF8')
req = urllib.request.Request(url='http://' + HOST + HOMEURL)
opener.open(req)
cookistr = ''
for item in cookie:
cookistr = cookistr + '%s=%s' % (item.name, item.value)
headers = {}
headers.clear()
headers = {'Content-type': 'application/x-www-form-urlencoded', "Accept": "text/plain", "Connection": "keep-alive"}
headers['Cookie'] = cookistr
loginpage = urllib.request.Request(url='http://' + HOST + AUTHURL, data=AUTHBODY, headers=headers)
opener.open(loginpage) #### 408
cookistr = ''
for item in cookie:
cookistr = cookistr + '%s=%s' % (item.name, item.value)
headers = {}
headers.clear()
headers = {'Content-type': 'application/x-www-form-urlencoded', "Accept": "text/plain", "Connection": "keep-alive"}
headers['Cookie'] = cookistr
return headers
转载于:https://blog.51cto.com/strongit/2129484