Example of implementing the rest request api in python

Source: Internet
Author: User
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 ']

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.