API是给别人用的,就要告诉别人如何发现api,以及api的用途、名称、出参、入参,生成api文档的做法有好多种,本文选了一种最简单的方式。
核心就是通过app.view_functions
这个字典找到每个API 的endpoint所绑定的方法,然后访问方法的名字和文档即可
这里先列举1688平台API的一个文档说明再教大家如何构建API文档!
1688 API 接入说明
-
API地址:申请KEY调用地址
-
调用示例:
<?php // 请求示例 url 默认请求参数已经URL编码处理 // 本示例代码未加密secret参数明文传输,若要加密请参考:https://open.onebound.cn/help/demo/sdk/demo-sign.php $method = "GET"; $url = "https://api-gw.onebound.cn/1688/item_get/?key=<您自己的apiKey>&secret=<您自己的apiSecret>&num_iid=610947572360"; $curl = curl_init(); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($curl, CURLOPT_FAILONERROR, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADER, true); curl_setopt($curl, CURLOPT_ENCODING, "gzip"); var_dump(curl_exec($curl)); ?>
-
参数说明
-
通用参数说明
- version:API版本
- key:调用key,测试key:test_api_key
- api_name:API类型[item_get,item_search]
- cache:[yes,no]默认yes,将调用缓存的数据,速度比较快
- result_type:[json,xml,serialize,var_export]返回数据格式,默认为json
- lang:[cn,en,ru] 翻译语言,默认cn简体中文
-
API:item_get 参数说明: num_iid:宝贝ID
-
-
此API目前支持以下基本接口:
- item_get 获得1688商品详情
- item_search 按关键字搜索商品
- item_search_img 按图搜索1688商品(拍立淘)
- item_search_suggest 获得搜索词推荐
- item_fee 获得商品快递费用
- seller_info 获得店铺详情
- item_search_shop 获得店铺的所有商品
- item_password 获得淘口令真实url
- upload_img 上传图片到1688
- item_search_seller 搜索店铺列表
- img2text 图片识别商品接口
- item_get_app 获取1688app上原数据
- buyer_order_list 获取购买到的商品订单列表
- cat_get 获得1688商品分类
Flask搭建api服务-生成API文档
从路由中搜索api,在这里可以构筑规则
def get_api_map():
"""Search API from rules, if match the pattern then we said it is API."""
for rule in app.url_map.iter_rules():
if 'docs' not in str(rule) and 'static' not in str(rule):
yield str(rule), rule.endpoint
建立两个路由,一个是api docs的首页,一个是各个api的规则定义
@app.route('/', methods=['GET'])
def index():
"""List all API to this page, api_map contains each api url + endpoint."""
api_map = sorted(list(get_api_map()))
index_url = url_for('index', _external=True)
api_map = [(index_url + x[0][1:], x[1]) for x in api_map]
return render_template('api_index.html', api_map=api_map)
@app.route('/docs/<endpoint>', methods=['GET'])def docs(endpoint):
"""Document page for an endpoint."""
api = {
'endpoint': endpoint,
'methods': [],
'doc': '',
'url': '',
'name': ''
}
try:
func = app.view_functions[endpoint]
api['name'] = _get_api_name(func)
api['doc'] = _get_api_doc(func)
for rule in app.url_map.iter_rules():
if rule.endpoint == endpoint:
api['methods'] = ','.join(rule.methods)
api['url'] = str(rule)
except:
api['doc'] = 'Invalid api endpoint: "{}"!'.format(endpoint)
return render_template('api_docs.html', api=api)
获取api的名称和api文档内容
def _get_api_name(func):
"""e.g. Convert 'do_work' to 'Do Work'"""
words = func.__name__.split('_')
words = [w.capitalize() for w in words]
return ' '.join(words)
def _get_api_doc(func):
if func.__doc__:
return func.__doc__
else:
return 'No doc found for this API!'
在原有的api函数内,补充晚上像个接口定义,包括入参、出参、名称、描述等等
@app.route('/getdimdict', methods=['GET', 'POST'])
def getdimdict():
"""
接口名称: /getdimdict 获取指标库的维度字典
接口描述:
获取指标库的维度字典,
接口入参: get方法
参数无
接口出参: json格式 data = {
"code":"200",
“info":"处理成功"
"result":{
"typecode": "datelevel\",
"typename": "\u65e5\\u671f\\u5c42\\u7ea7\",
"dimcode": "01",
"dimname": "\\u5e74\"
}
}
"""
params = {}
retinfo = {}
errorflag = False
retinfo['code'] = 200
retinfo['info'] = '处理成功'
retinfo['result'] = ''
sqltext = config[DBSECTION]['getdimdict']
jsonstr = getsqlresultjson(db, sqltext, params)
retinfo['result'] = jsonstr
response = jsonify(retinfo)
response.status_code = 200
return response
定义html的base页面-layout.html
{% extends "bootstrap/base.html" %}
{% block title %}Home{% endblock %}
{% block styles %}
{{ super() }}
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
{% endblock %}
{% block content %}
<div id="wrap">
<!-- Begin nav bar -->
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">API DOC DEMO</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
<!-- Begin page content -->
<div class="container">
<ul class="breadcrumb">
<li><a href="/">Home</a></li>
{% block breadcrumb_nav %}{% endblock %}
</ul>
<div class="page-header">
{% block page_header %}{% endblock %}
</div>
{% block content_area %}{% endblock %}
</div>
</div>
<div id="footer">
<div class="container">
<p class="text-muted credit">Copyright © <a href="https://github.com/tobyqin/">Toby Qin</a>
- <a href="https://github.com/tobyqin/flask_api_doc">Source at Github</a></p>
</div>
</div>
{% endblock %}
api_index.html
{% extends "./layout.html" %}
{% block title %}API Root{% endblock %}
{% block breadcrumb_nav %}
<li><a href="{{ url_for('index') }}">Api Root</a></li>
{% endblock %}
{% block page_header %}
<h1>Api Root</h1>
{% endblock %}
{% block content_area %}
<pre>{
{% for i in api_map %} "<a href="/docs/{{ i[1] }}">{{ i[0] }}</a>"{{ ",\n" if not loop.last }}{% endfor %}
}</pre>
{% endblock %}
api_docs.html
{% extends "./layout.html" %}
{% block title %}API - {{ api['name'] }}{% endblock %}
{% block breadcrumb_nav %}
<li><a href="{{ url_for('index') }}">Api Root</a></li>
<li><a href="{{ api['url'] }}">{{ api['name'] }}</a></li>
{% endblock %}
{% block page_header %}
<h1>{{ api['name'] | upper }}</h1>
{% endblock %}
{% block content_area %}
<pre>
<b>Target:</b><span><a href="{{ api['url'] }}">{{ api['url'] }}</a></span>
<b>Allow :</b> <span>{{ api['methods'] }}</span>
<b>Usage :</b> <span>{{ api['doc'] }}</span>
</pre>
{% endblock %}
api首页的页面如下:
具体api的像个文档
最后,谢谢关注,谢谢支持!
。