This article mainly introduces the example of implementing the rest request api in python. if you need it, refer to the Sina python api for reference. it is applicable to open-source api requests.
The code is as follows:
#-*-Coding: UTF-8 -*-
Import collections
Import gzip
Import urllib
Import urllib2
From urlparse import urlparse
Try:
From cStringIO import StringIO
Failed T ImportError:
From StringIO import StringIO
Try:
Import json
Failed T ImportError:
Import simplejson as json
_ Author _ = 'myth'
_ HTTP_GET = 1
_ HTTP_POST = 2
# Timeout (seconds)
TIMEOUT = 45
RETURN_TYPE = {"json": 0, "xml": 1, "html": 2, "text": 3}
_ METHOD_MAP = {'get': _ HTTP_GET, 'Post': _ HTTP_POST}
Class APIError (StandardError ):
"""
Raise APIError if processing ing json message indicating failure.
"""
Def _ init _ (self, error_code, error, request ):
Self. error_code = error_code
Self. error = error
Self. request = request
StandardError. _ init _ (self, error)
Def _ str _ (self ):
Return 'apierror: % s, request: % s' % (self. error_code, self. error, self. request)
# Def callback_type (return_type = 'json '):
#
# Default_type = "json"
# Default_value = RETURN_TYPE.get (default_type)
# If return_type:
# If isinstance (return_type, (str, unicode )):
# Default_value = RETURN_TYPE.get (return_type.lower (), default_value)
# Return default_value
Def _ format_params (_ pk = None, encode = None, ** kw ):
"""
: Param kw:
: Type kw:
: Param encode:
: Type encode:
: Return:
: Rtype:
"""
_ Pk = '% s [% s]' % _ pk if _ pk else '% s'
Encode = encode if encode else urllib. quote
For k, v in kw. iteritems ():
_ K = _ pk % k
If isinstance (v, basestring ):
Qv = v. encode ('utf-8') if isinstance (v, unicode) else v
_ V = encode (qv)
Yield _ k, _ v
Elif isinstance (v, collections. Iterable ):
If isinstance (v, dict ):
For _ ck, _ cv in _ format_params (_ pk = _ k, encode = encode, ** v ):
Yield _ ck, _ cv
Else:
For I in v:
Qv = I. encode ('utf-8') if isinstance (I, unicode) else str (I)
_ V = encode (qv)
Yield _ k, _ v
Else:
Qv = str (v)
_ V = encode (qv)
Yield _ k, _ v
Def encode_params (** kw ):
"""
Do url-encode parameters
>>> Encode_params (a = 1, B = 'R & D ')
'A = 1 & B = R % 26d'
>>> Encode_params (a = u' \ u4e2d \ u6587 ', B = ['A',' B ', 123])
'A = % E4 % B8 % AD % E6 % 96% 87 & B = a & B = B & B = 100'
>>> Encode_params (**{
'A1': {'Aa1': 1, 'aa2 ': {'aaa1': 11 }},
'B1 ': [1, 2, 3, 4],
'C1': {'cc1': 'C', 'cc2': ['Q', 1, '@'], 'cc3': {'ccc1 ': ['s ', 2]}
})
'A1 [aa1] = 1 & a1 [aa2] [aaa1] = 11 & c1 [PC3] = C & c1 [cc3] [ccc1] = s & c1 [cc3] [ccc1] = 2 & c1 [cc2] = Q & c1 [cc2] = 1 & c1 [cc2] = % 40 & b1 = 1 & b1 = 2 & b1 = 3 & b1 = 4'
"""
# Args = []
# For k, v in kw. iteritems ():
# If isinstance (v, basestring ):
# Qv = v. encode ('utf-8') if isinstance (v, unicode) else v
# Args. append ('% s = % s' % (k, urllib. quote (qv )))
# Elif isinstance (v, collections. Iterable ):
# For I in v:
# Qv = I. encode ('utf-8') if isinstance (I, unicode) else str (I)
# Args. append ('% s = % s' % (k, urllib. quote (qv )))
# Else:
# Qv = str (v)
# Args. append ('% s = % s' % (k, urllib. quote (qv )))
# Return '&'. join (args)
Args = []
_ Urlencode = kw. pop ('_ urlencode', urllib. quote)
For k, v in _ format_params (_ pk = None, encode = _ urlencode, ** kw ):
Args. append ('% s = % s' % (k, v ))
Args = sorted (args, key = lambda s: s. split ("=") [0])
Return '&'. join (args)
Def _ read_body (obj ):
Using_gzip = obj. headers. get ('content-encoding', '') = 'gzip'
Body = obj. read ()
If using_gzip:
Gzipper = gzip. GzipFile (fileobj = StringIO (body ))
Fcontent = gzipper. read ()
Gzipper. close ()
Return fcontent
Return body
Class JsonDict (dict ):
"""
General json object that allows attributes to be bound to and also behaves like a dict
"""
Def _ getattr _ (self, attr ):
Try:
Return self [attr]
Failed T KeyError:
Raise AttributeError (r "'jsonid' object has no attribute '% s'" % attr)
Def _ setattr _ (self, attr, value ):
Self [attr] = value
Def _ parse_json (s ):
"""
Parse str into JsonDict
"""
Def _ obj_hook (pairs ):
"""
Convert json object to python object
"""
O = JsonDict ()
For k, v in pairs. iteritems ():
O [str (k)] = v
Return o
Return json. loads (s, object_hook = _ obj_hook)
Def _ parse_xml (s ):
"""
Parse str into xml
"""
Raise NotImplementedError ()
Def _ parse_html (s ):
"""
Parse str into html
"""
Raise NotImplementedError ()
Def _ parse_text (s ):
"""
Parse str into text
"""
Raise NotImplementedError ()
Def _ http_call (the_url, method, return_type = "json", request_type = None, request_suffix = None, headers = {}, _ timeout = 30, ** kwargs ):
"""
The_url: request address
Method request method (get, post)
Return_type: return format parsing
Request_suffix: the suffix of the request address, such as jsp and net.
_ Timeout: timeout
Kwargs: request parameters
"""
Http_url = "% s. % s" (the_url, request_suffix) if request_suffix else the_url
If request_type = 'json ':
Headers ['content-type'] = 'application/json'
# Method = _ HTTP_POST
# Json_data = json. dumps (kwargs)
# Convert str to bytes (ensure encoding is OK)
# Params = json_data.encode ('utf-8 ')
Params = json. dumps (kwargs)
Else:
Params = encode_params (** kwargs)
Http_url = '% s? % S' % (http_url, params) if method = _ HTTP_GET else http_url
Print http_url
# U = urlparse (http_url)
# Headers. setdefault ("host", u. hostname)
Http_body = None if method = _ HTTP_GET else params
Req = urllib2.Request (http_url, data = http_body, headers = headers)
Callback = globals (). get ('_ parse _ {0}'. format (return_type ))
If not hasattr (callback, '_ call __'):
Print "return '% s' unable to resolve" % return_type
Callback = _ parse_json
Try:
Resp = urllib2.urlopen (req, timeout = _ timeout if _ timeout else TIMEOUT)
Body = _ read_body (resp)
R = callback (body)
# If hasattr (r, 'error _ code '):
# Raise APIError (r. error_code, r. get ('error', ''), r. get ('request ',''))
Return r
Failed T urllib2.HTTPError, e:
Try:
Body = _ read_body (e)
R = callback (body)
Return r
Except t:
R = None
# If hasattr (r, 'error _ code '):
# Raise APIError (r. error_code, r. get ('error', ''), r. get ('request ',''))
Raise e
Class HttpObject (object ):
Def _ init _ (self, client, method ):
Self. client = client
Self. method = method
Def _ getattr _ (self, attr ):
Def wrap (** kw ):
If attr:
The_url = '% s/% s' % (self. client. api_url, attr. replace ('__','/'))
Else:
The_url = self. client. api_url
Return _ http_call (the_url, self. method, ** kw)
Return wrap
Def _ call _ (self, ** kw ):
Return _ http_call (self. client. api_url, self. method, ** kw)
Class APIClient (object ):
"""
Usage:
For example, the api request address is: http://api.open.zbjdev.com/kuaiyinserv/kuaiyin/billaddress
Request method: GET
The required parameter is the UID of user_id.
Is_all: whether to query all data. 0 is the default mailing address. 1 is the whole mailing address.
Access_token platform authentication
The returned data is json.
The following code is used:
Domain = "api.open.zbjdev.com"
# For https requests, set is_https to True.
Client = APIClient (domain)
Data = {"user_id": "14035462", "is_all": 1, "access_token": "XXXXXXXXXX "}
# For post requests, change the get method to the post method.
Result = client. kuaiyinserv. kuaiyin. billaddress. get (return_type = "json", ** data)
# Equivalent
# Result = client. kuaiyinserv _ kuaiyin _ billaddress _ get (return_type = "json", ** data)
# Result = client. kuaiyinserv _ kuaiyin _ billaddress (return_type = "json", ** data)
"""
Def _ init _ (self, domain, is_https = False ):
Http = "http"
If domain. startswith ("http: //") or domain. startswith ("https ://"):
Http, domain = domain. split ("://")
# Else:
If is_https:
Http = "https"
Self. api_url = ('% s: // % s' % (http, domain). rstrip ("/")
Self. get = HttpObject (self, _ HTTP_GET)
Self. post = HttpObject (self, _ HTTP_POST)
Def _ getattr _ (self, attr ):
If '_' in attr:
Method = self. get
If attr [-6:] = "_ post ":
Attr = attr [:-6]
Method = self. post
Elif attr [-5:] = "_ get ":
Attr = attr [:-5]
If attr [: 2] = '__':
Attr = attr [2:]
Return getattr (method, attr)
Return _ Callable (self, attr)
Class _ Executable (object ):
Def _ init _ (self, client, method, path ):
Self. _ client = client
Self. _ method = method
Self. _ path = path
Def _ call _ (self, ** kw ):
Method = _ METHOD_MAP [self. _ method]
Return _ http_call ('% s/% s' % (self. _ client. api_url, self. _ path), method, ** kw)
Def _ str _ (self ):
Return '_ Executable (% s)' % (self. _ method, self. _ path)
_ Repr _ = _ str __
Class _ Callable (object ):
Def _ init _ (self, client, name ):
Self. _ client = client
Self. _ name = name
Def _ getattr _ (self, attr ):
If attr = 'get ':
Return _ Executable (self. _ client, 'get', self. _ name)
If attr = 'Post ':
Return _ Executable (self. _ client, 'post', self. _ name)
Name = '% s/% s' % (self. _ name, attr)
Return _ Callable (self. _ client, name)
Def _ str _ (self ):
Return '_ Callable (% s)' % self. _ name
_ Repr _ = _ str __
Def test_logistics ():
Domain = "https://api.kuaidi100.com/api"
# For https requests, set is_https to True.
Client = APIClient (domain)
Data = {"id": "45f2d1f2sds", "com": "yunda", "nu": "1500066330925 "}
Result = client. _ get (_ timeout = 2, ** data)
Print result
Print result ["message"]
Print result. get ("message ")
Print result. message
If _ name _ = '_ main __':
# Test_logistics ()
Data = {
"Data ":{
"Id": 1,
"Pid": 3,
"Name": u'aston'
},
"Sign": 'asdfdsdsfsdf ',
}
Domain = "kuaiyin.zhubajie.com"
Client = APIClient (domain)
# Headers = {'content-type': 'application/json '}
Headers = {"host": domain}
Result = client.api.zhubajie.fz.info. post (return_type = "json", request_type = "json", headers = headers, ** data)
Print result
Print result ['data'] ['MSG ']
C = APIClient ('task .6.zbj.cn ')
R = getattr (c. api, 'kuaiyin-action-delcache'). post (request_type = "json ",
Headers = {},
** {"Sign ":"",
"Data ":{
"Product": "pvc ",
"Category": "card ",
"Req_type": "pack_list"
}})
Print r
Print r ['data'] ['MSG ']