python实现rest请求api示例

该代码参考新浪python api,适用于各个开源api请求

代码如下:

# -*- coding: utf-8 -*-
import collections
import gzip
import urllib
import urllib2
from urlparse import urlparse

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

try:
    import json
except ImportError:
    import simplejson as json

__author__ = 'myth'

_HTTP_GET = 1
_HTTP_POST = 2
# 超时时间(秒)
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 receiving 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: %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=123'

>>> 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[cc1]=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]
        except KeyError:
            raise AttributeError(r"'JsonDict' 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: 请求地址
    method 请求方法(get,post)
    return_type: 返回格式解析
    request_suffix: 请求地址的后缀,如jsp,net
    _timeout: 超时时间
    kwargs: 请求参数
    """

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
    except urllib2.HTTPError, e:
        try:
            body = _read_body(e)
            r = callback(body)
            return r
        except:
            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):
    """
    使用方法:
        比如:api 请求地址为:http://api.open.zbjdev.com/kuaiyinserv/kuaiyin/billaddress
             请求方式为: GET
             需要的参数为:user_id 用户的UID
                         is_all 是否查询所有数据,0为默认邮寄地址 1为全部邮寄地址
                         access_token 平台认证
             返回数据为:json

那么此时使用如下:
        domain = "api.open.zbjdev.com"
        #如果是https请求,需要将is_https设置为True
        client = APIClient(domain)
        data = {"user_id": "14035462", "is_all": 1, "access_token": "XXXXXXXXXX"}
        # 如果是post请求,请将get方法改为post方法
        result = client.kuaiyinserv.kuaiyin.billaddress.get(return_type="json", **data)
        #等同于
        # 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 %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"

#如果是https请求,需要将is_https设置为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'中的阿斯顿'
        },
        "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']

(0)

相关推荐

  • python网络编程学习笔记(九):数据库客户端 DB-API

    一.DB-API概述      python支持很多不同的数据库.由于不同的卖家服务器导致和数据库通信的网络协议各有不同.在python的早期版本中,每一种数据库都带有自己的python模块,所有这些模块以不同的方式工作,并提供不同的函数.这种方法不便于编写能够在多种数据库服务器类型中运行的代码,于是DB-API库函数产生.在DB-API中,所有连接数据库的模块即便是底层网络协议不同,也会提供一个共同的接口.这一点和JAVA中的JDBC和ODBC类似.       DB-API下载地址:http

  • python使用新浪微博api上传图片到微博示例

    复制代码 代码如下: import urllib.parse,os.path,time,sysfrom http.client import HTTPSConnectionfrom PyQt5.QtCore import *from PyQt5.QtGui import *from PyQt5.QtWidgets import * #pathospath=sys.path[0]if len(ospath)!=3:    ospath+='\\'ospath=ospath.replace('\\'

  • python使用ctypes模块调用windowsapi获取系统版本示例

    python使用ctypes模块调用windows api GetVersionEx获取当前系统版本,没有使用python32 复制代码 代码如下: #!c:/python27/python.exe#-*- coding:utf-8 -*- "通过调用Window API判断当前系统版本"# 演示通过ctypes调用windows api函数.# 作者已经知道python32能够实现相同功能# 语句末尾加分号,纯属个人习惯# 仅作部分版本判断,更详细的版本判断推荐系统OSVERSION

  • python翻译软件实现代码(使用google api完成)

    复制代码 代码如下: # -*- coding: utf-8 -*- import httplibfrom urllib import urlencodeimport re def out(text):    p = re.compile(r'","')    m = p.split(text)    print m[0][4:].decode('UTF-8').encode('GBK') if __name__=='__main__':    while True:        w

  • Python使用新浪微博API发送微博的例子

    1.注册一个新浪应用,得到appkey和secret,以及token,将这些信息写入配置文件sina_weibo_config.ini,内容如下,仅举例: 复制代码 代码如下: [userinfo]CONSUMER_KEY=8888888888CONSUMER_SECRET=777777f3feab026050df37d711200000TOKEN=2a21b19910af7a4b1962ad6ef9999999TOKEN_SECRET=47e2fdb0b0ac983241b0caaf45555

  • python使用在线API查询IP对应的地理位置信息实例

    这篇文章中的内容是来源于去年我用美国的VPS搭建博客的初始阶段,那是有很多恶意访问,我就根据access log中的源IP来进行了很多统计,同时我也将访问量最高的恶意访问的源IP拿来查询其地理位置信息.所以,我就用到了根据IP查询地理位置信息的一些东西,现在将这方面积累的一点东西共享出来. 根据IP查询所在地.运营商等信息的一些API如下(根据我有限的一点经验):1. 淘宝的API(推荐):http://ip.taobao.com/service/getIpInfo.php?ip=110.84.

  • gearman的安装启动及python API使用实例

    本文讲述了gearman的安装启动及python API使用实例,对于网站建设及服务器维护来说非常有用! 一.概述: Gearman是一款非常优秀的任务分发框架,可以用于分布式计算.具体的gearmand服务的安装启动及gearman的python 模块的安装以及简单示例如下:   操作系统:rnel 5.7 1. 首先,我们需要安装gearmand,在centos和rhel环境下,我们只需运行以下命令: yum install gearmand -y   注意:如果不希望通过yum的方式来安装

  • rhel5.7下安装gearmand及启动的方法

    本文简述了在rhel5.7下安装gearmand及启动的方法,供大家学习参考! 首先,到官网https://launchpad.net/gearmand/下载gearmand的源码包,传到rhel5.7的系统上,并解压.   运行configure: [@localhost gearmand-1.1.11]# ./configure --prefix=/usr/local/gearman --with-mysql --with-sqlite3=no 这时候会出现报如下错误: checking f

  • python调用windows api锁定计算机示例

    调用Windows API锁定计算机 本来想用Python32直接调用,可是没有发现Python32有Windows API LockWorkStation(); 因此,就直接调用Windows DLL了 复制代码 代码如下: #!/usr/bin/env python#-*- coding:cp936 -*- "调用WindowAPI锁定计算机" import ctypes; dll = ctypes.WinDLL('user32.dll'); dll.LockWorkStation

  • python实现rest请求api示例

    该代码参考新浪python api,适用于各个开源api请求 复制代码 代码如下: # -*- coding: utf-8 -*-import collectionsimport gzipimport urllibimport urllib2from urlparse import urlparse try:    from cStringIO import StringIOexcept ImportError:    from StringIO import StringIO try:   

  • 详解Python Flask API 示例演示(附cookies和session)

    目录 一.概述 二.常用函数讲解 1)Flask() 函数 2)route() 函数 3)jsonify() 函数 4)render_template() 函数 5)redirect() 函数 6)url_for() 函数 7)before_request() 函数 8)after_request() 函数 9)abort() 函数 10)send_file() 函数 三.常用对象讲解 1)request 对象 2)session 对象 四.Flask 中的 cookies 与 session

  • Python使用grequests并发发送请求的示例

    前言 requests是Python发送接口请求非常好用的一个三方库,由K神编写,简单,方便上手快.但是requests发送请求是串行的,即阻塞的.发送完一条请求才能发送另一条请求. 为了提升测试效率,一般我们需要并行发送请求.这里可以使用多线程,或者协程,gevent或者aiohttp,然而使用起来,都相对麻烦. grequests是K神基于gevent+requests编写的一个并发发送请求的库,使用起来非常简单. 安装方法: pip install gevent grequests 项目地

  • Python编程调用百度API实现地理位置经纬度坐标转换示例

    目录 1.1,用百度账号登陆百度地图控制台 1.2,创建一个应用,获取 AK 参数 1.3,地理编码.逆地理编码 1.3.1 地理编码 1.3.2 逆地理编码 经纬度坐标转换最常见办法就是调用第三方 API,例如百度.高德地图等服务平台,提供了相应的功能接口,它们的这类技术已经非常成熟啦,准确稳定,关键还是免费的 ~ 本期教程以百度为例(高德的用方类似),介绍一下其用法 1.1,用百度账号登陆百度地图控制台 百度地图开放平台 1.2,创建一个应用,获取 AK 参数 登录控制台之后,选择左侧 应用

  • python获取http请求响应头headers中的数据的示例

    例如我要测试一个创建网络的接口,需要先拿token值,而获取token的接口请求成功后,将token存在了响应头headers,postman调接口如下,现在想要通过python获取下图中 X-Subject-Token的值,供后续接口使用 方法:仅需要python的requests库就可以实现 示例: #!/usr/bin/env python # -*- coding: utf-8 -*- # @File : 1.py # @Author: ttwang # @Date : 2022/2/1

  • 利用python的socket发送http(s)请求方法示例

    前言 这是个在写计算机网络课设的时候碰到的问题,卡了我一天,所以总结一下. 其实在之前就有用requests写过python爬虫,但是计算机网络要求更底层的实现,刚好我看到了[这篇文章]1结果发现他就是用socket来实现的请求,所以就学习了. 本来也觉得应该不难,毕竟就是建立tcp连接. 原网站的例子如下: def fetch(url): sock = socket.socket() # 建立socket sock.connect(('xkcd.com', 80)) # 远程连接 reques

  • python通过百度地图API获取某地址的经纬度详解

    前言 这几天比较空闲,就接触了下百度地图的API(开发者中心链接地址:http://developer.baidu.com),发现调用还是挺方便的,本文将给大家详细的介绍关于python通过百度地图API获取某地址的经纬度的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 申请百度API 1.打开网页 http://lbsyun.baidu.com/index.php?title=首页 选择功能与服务中的地图,点击左边的获取密匙,然后按照要求申请即可,需要手机和百度账号

  • Python如何使用Gitlab API实现批量的合并分支

    这篇文章主要介绍了Python如何使用Gitlab API实现批量的合并分支,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.需求:每次大批量上线完成后,都会进行将hotfix合并到Master,合并到test/uat等等重复操作(上线发布后自动合并master已完成). 2.现实:在完成发布后自动合并master后,可能还有的项目人员忘记合并到其他分支的情况,so #!/usr/bin/python3 #coding=utf-8 # 自动合

  • Python实现异步IO的示例

    前言 用阻塞 API 写同步代码最简单,但一个线程同一时间只能处理一个请求,有限的线程数导致无法实现万级别的并发连接,过多的线程切换也抢走了 CPU 的时间,从而降低了每秒能够处理的请求数量.为了达到高并发,你可能会选择一个异步框架,用非阻塞 API 把业务逻辑打乱到多个回调函数,通过多路复用与事件循环的方式实现高并发. 磁盘 IO 为例,描述了多线程中使用阻塞方法读磁盘,2 个线程间的切换方式.那么,怎么才能实现高并发呢? 把上图中本来由内核实现的请求切换工作,交由用户态的代码来完成就可以了,

  • python+appium实现自动化测试的示例代码

    目录 1.什么是Appium 2.启动一个app自动化程序的步骤 3.appium服务介绍 4. appium客户端使用 5.adb的使用 6.Appium启动过程分析 1.什么是Appium appium是一个开源的测试自动化框架,可以与原生的.混合的和移动的web应用程序一直使用.它使用WebDriver协议驱动IOS(内置的测试引擎xcuitest).Android(uiautomator2,Espresso)和Windows应用程序 原生应用程序:安卓程序是用JAVA或kotlin开发出

随机推荐