淘宝api Python 接口升级 3.0 版本
因为自学 python 工作中会经常用到淘宝Api调用数据 一直以来后台下载的淘宝Api 都是2.7版本
还是12年 lihao同学编写,一直没有升级
用Python 自带的2to3脚本工具升级后 大部分接口 调用正常
但是上传图片接口 一直提示错误
由于是初学 只能网上找资料了 找了很多资料 都没解决
最后通过国外友人的一篇博客 找到了解决方法
在这里分享一下 希望能帮助其他人 只要替换 base.py 代码就可以 初步测试调用接口 都能成功
# -*- coding: utf-8 -*- """ Created on 2012-7-3 @author: lihao """ try: import httplib except ImportError: import http.client as httplib import urllib import time import hashlib import json import io import top import sys import itertools import mimetypes from urllib.parse import urlencode import codecs ''' 定义一些系统变量 ''' SYSTEM_GENERATE_VERSION = "taobao-sdk-python-20151217" P_APPKEY = "app_key" P_API = "method" P_SESSION = "session" P_ACCESS_TOKEN = "access_token" P_VERSION = "v" P_FORMAT = "format" P_TIMESTAMP = "timestamp" P_SIGN = "sign" P_SIGN_METHOD = "sign_method" P_PARTNER_ID = "partner_id" P_CODE = 'code' P_SUB_CODE = 'sub_code' P_MSG = 'msg' P_SUB_MSG = 'sub_msg' N_REST = '/router/rest' writer = codecs.lookup('utf-8')[3] def sign(secret, parameters): # =========================================================================== # '''签名方法 # @param secret: 签名需要的密钥 # @param parameters: 支持字典和string两种 # ''' # =========================================================================== # 如果parameters 是字典类的话 if hasattr(parameters, "items"): # keys = parameters.keys() keys = list(parameters.keys()) # sudoz: Py3 keys.sort() parameters = "%s%s%s" % (secret, str().join( '%s%s' % (key, parameters[key]) for key in keys), secret) # sign = hashlib.md5(parameters).hexdigest().upper() sign = hashlib.md5(parameters.encode('utf8')).hexdigest().upper() # sudoz: Py3 print(sign) return sign def mixStr(pstr): if (isinstance(pstr, str)): return pstr # elif(isinstance(pstr, unicode)): elif (isinstance(pstr, bytes)): # sudoz: Py3 return ascii(pstr) else: return str(pstr) class FileItem(object): def __init__(self, filename=None, content=None): self.filename = filename self.content = content class MultiPartForm(object): """Accumulate the data to be used when posting a form.""" def __init__(self): self.form_fields = [] self.files = [] self.boundary = "PYTHON_SDK_BOUNDARY" return def get_content_type(self): return 'multipart/form-data; boundary=%s' % self.boundary def add_field(self, name, value): """Add a simple field to the form data.""" self.form_fields.append((name, str(value))) return def add_file(self, fieldname, filename, fileHandle, mimetype=None): """Add a file to be uploaded.""" if mimetype is None: mimetype = mimetypes.guess_type(filename)[ 0] or 'application/octet-stream' self.files.append((fieldname, filename,fileHandle, mimetype)) return # =================================================================================== @classmethod def u(cls, s): if sys.hexversion < 0x03000000 and isinstance(s, str): s = s.decode('utf-8') if sys.hexversion >= 0x03000000 and isinstance(s, bytes): s = s.decode('utf-8') return s def iter(self, fields, files): """ fields is a sequence of (name, value) elements for regular form fields. files is a sequence of (name, filename, file-type) elements for data to be uploaded as files Yield body's chunk as bytes """ encoder = codecs.getencoder('utf-8') for (key, value) in fields: key = self.u(key) yield encoder('--{}\r\n'.format(self.boundary)) yield encoder(self.u('Content-Disposition: form-data; name="{}"\r\n').format(key)) yield encoder('\r\n') if isinstance(value, int) or isinstance(value, float): value = str(value) yield encoder(self.u(value)) yield encoder('\r\n') for (key, filename, fileHander,content_type) in files: key = self.u(key) filename = self.u(filename) yield encoder('--{}\r\n'.format(self.boundary)) yield encoder(self.u('Content-Disposition: form-data; name="{}"; filename="{}"\r\n').format(key, filename)) print(content_type) yield encoder('Content-Type: {}\r\n'.format(content_type)) yield encoder('\r\n') buff = fileHander.read() yield (buff, len(buff)) yield encoder('\r\n') yield encoder('--{}--\r\n'.format(self.boundary)) #================================================================================= def __bytes__(self): body = io.BytesIO() for chunk, chunk_len in self.iter(self.form_fields, self.files): body.write(chunk) return body.getvalue() class TopException(Exception): # =========================================================================== # 业务异常类 # =========================================================================== def __init__(self): self.errorcode = None self.message = None self.subcode = None self.submsg = None self.application_host = None self.service_host = None def __str__(self, *args, **kwargs): sb = "errorcode=" + mixStr(self.errorcode) + \ " message=" + mixStr(self.message) + \ " subcode=" + mixStr(self.subcode) + \ " submsg=" + mixStr(self.submsg) + \ " application_host=" + mixStr(self.application_host) + \ " service_host=" + mixStr(self.service_host) return sb class RequestException(Exception): # =========================================================================== # 请求连接异常类 # =========================================================================== pass class RestApi(object): # =========================================================================== # Rest api的基类 # =========================================================================== def __init__(self, domain='gw.api.taobao.com', port=80): # ======================================================================= # 初始化基类 # Args @param domain: 请求的域名或者ip # @param port: 请求的端口 # ======================================================================= self.__domain = domain self.__port = port self.__httpmethod = "POST" if (top.getDefaultAppInfo()): self.__app_key = top.getDefaultAppInfo().appkey self.__secret = top.getDefaultAppInfo().secret def get_request_header(self): return { 'Content-type': 'application/x-www-form-urlencoded;charset=UTF-8', "Cache-Control": "no-cache", "Connection": "Keep-Alive", } def set_app_info(self, appinfo): # ======================================================================= # 设置请求的app信息 # @param appinfo: import top # appinfo top.appinfo(appkey,secret) # ======================================================================= self.__app_key = appinfo.appkey self.__secret = appinfo.secret def getapiname(self): return "" def getMultipartParas(self): return [] def getTranslateParas(self): return {} def _check_requst(self): pass def getResponse(self, authrize=None, timeout=30): # ======================================================================= # 获取response结果 # ======================================================================= # connection = httplib.HTTPConnection(self.__domain, self.__port, False, # timeout) connection = httplib.HTTPConnection(self.__domain, self.__port, timeout) # sudoz: Py3 sys_parameters = { P_FORMAT: 'json', P_APPKEY: self.__app_key, P_SIGN_METHOD: "md5", P_VERSION: '2.0', # P_TIMESTAMP: str(long(time.time() * 1000)), P_TIMESTAMP: str(int(time.time() * 1000)), # sudoz: Py3 P_PARTNER_ID: SYSTEM_GENERATE_VERSION, P_API: self.getapiname(), } if authrize is not None: sys_parameters[P_SESSION] = authrize application_parameter = self.getApplicationParameters() sign_parameter = sys_parameters.copy() sign_parameter.update(application_parameter) sys_parameters[P_SIGN] = sign(self.__secret, sign_parameter) connection.connect() header = self.get_request_header() if self.getMultipartParas(): form = MultiPartForm() for key, value in application_parameter.items(): form.add_field(key, value) for key in self.getMultipartParas(): fileitem = getattr(self, key) if fileitem and isinstance(fileitem, FileItem): form.add_file(key, fileitem.filename, fileitem.content) #传入二进制信息 body =bytes(form) header['Content-type'] = form.get_content_type() else: # body = urllib.urlencode(application_parameter) body = urllib.parse.urlencode(application_parameter) # sudoz: Py3 # url = N_REST + "?" + urllib.urlencode(sys_parameters) url = N_REST + "?" + urllib.parse.urlencode(sys_parameters) # sudoz: Py3 connection.request(self.__httpmethod, url, body=body, headers=header) print(connection.host) response = connection.getresponse() if response.status is not 200: raise RequestException('invalid http status ' + str( response.status) + ',detail body:' + response.read()) # result = response.read() result = response.read().decode('utf-8') # sudoz: Py3里JSON只接收unicode jsonobj = json.loads(result) return jsonobj def getApplicationParameters(self): application_parameter = {} # for key, value in self.__dict__.iteritems(): for key, value in self.__dict__.items(): if not key.startswith( "__") and not key in self.getMultipartParas() and not key.startswith( "_RestApi__") and value is not None: if (key.startswith("_")): application_parameter[key[1:]] = value else: application_parameter[key] = value # 查询翻译字典来规避一些关键字属性 translate_parameter = self.getTranslateParas() # for key, value in application_parameter.iteritems(): for key, value in application_parameter.items(): # sudoz: Py3 if key in translate_parameter: application_parameter[translate_parameter[key]] = \ application_parameter[key] del application_parameter[key] return application_parameter
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
windows开发的一个诡异坑,百年一遇?
今天项目组的小朋友遇到了一个很奇怪的问题 一个工程,在IDEA中运行十分正常,但是线上就是报错,报找不到类 但反编译之后明明类就在,但本地怎么运行也复现不出线上的问题,就是能正常运行 小朋友也很着急,时间也过去了不少,于是来求助我 在帮小朋友排除了一些猜测之后找到了罪魁祸首 windows的大小写不敏感 大家都知道windows是大小写不敏感的,同一个单词无论大小写都被认为是相同的东西 而linux是大小写敏感的,大小写不同被认为是两个东西 这次的问题就出在一个包名上,这个包名命名不规范,用了驼峰式的命名,包含一个大写字母 testUp 所有类中import的部分都是大写,而实际打在jar包中的目录是全小写,导致在linux这个敏感环境下就找不到这个含有大写的路径了 有人说这不是很简单的问题么,谁让大小写不一致呢,活该 那我为什么说这是百年一遇呢 原因就在于打包都是由IDE完成的,我们IDE用的是IDEA,使用maven install进行打包 理论上是不应该出现这个问题的,以前也从来没遇到过,我今天又做了很多的测试也再没复现过 真的变成了一桩悬案,有可能是在某种极其特殊的场景下的一个...
- 下一篇
Json反序列化与Java泛型
Java的JSON库有很多,本文分析google的Gson和alibaba的fastjson,在Java泛型场景反序列化的一些有意思的行为。考虑下面的json字符串: [ "2147483648", "2147483647" ] 用fastjson在不指定类型的情况下解析,下面的代码输出啥: JSON.parseArray(s).forEach(o -> { System.out.println(o.getClass()); }); 答案是: class java.lang.Long class java.lang.Integer 是不是感觉有点儿奇怪,两个都是数字啊,居然输出了不同的类型,原因我们下面细讲。再看看Gson, 用Gson解析并且不指定泛型类型的话,下面的代码输出啥: new Gson().fromJson(s, List.class).forEach(o -> { System.out.println(o.getClass()); }); 答案是: class java.lang.Double class java.lang.Double 这次两个都是Dou...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS关闭SELinux安全模块
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7安装Docker,走上虚拟化容器引擎之路