比過黑客松或是數據探勘一定多少接觸過api,可是呼叫api一行指令的背後又是怎麼做的呢?
上網找了幾筆文章發現原來有個很簡單的方式可以建立自己的api,那就是使用flask框架。flask架構簡單運行速度比Django快,且同樣也是使用簡單易懂的Python語言(撒花),通常適合用來做static 網頁的後段。而這裡我就以flask為框架弄出一個能parse 出json 資料的api
安裝:
在unix上,開啟terminal 安裝virtualenv
sudo pip install virtualenv
成立一個flask folder, 在folder內創建一個隔絕的Python 環境。
virtualenv myvenv
啟動Python環境(退出則是: deactivate)
source myvenv/bin/activate
安裝flask : pip install Flask
之後成立一個app.py檔案,裡面寫著:
from flask import Flask, jsonify app = Flask(__name__) data = [ { 'id':1233, 'name':u'Jason', 'description':u'handsome but impatient' }, { 'id':1234, 'name':u'Peter', 'description':u'tall and humorous' } ] @app.route("/example/api/v0.1/name",methods = ['GET']) def get_data(): return jsonify({'data':data}) if __name__ == "__main__": app.run(debug = True)
其中data是你的數據List,。當有人GET時,flask就會將data轉為json格式並回傳給他內所data內容。
執行: python app.py
在另一個terminal視窗執行: curl -i http://localhost:5000/example/api/v0.1/data
輸出結果如下(結果在右邊):
旁邊的terminal
如果想要parse單筆資料要怎麼辦呢?
from flask import Flask, jsonify app = Flask(__name__) data = [ { 'id':1233, 'name':u'Jason', 'description':u'handsome but impatient' }, { 'id':1234, 'name':u'Peter', 'description':u'tall and humorous' } ] @app.route("/example/api/v0.1/name/<int:data_id>",methods = ['GET']) def get_data(data_id): people = [people for people in data if people['id'] == data_id ] if len(people) == 0: abort(404) return jsonify({'data':people[0]}) @app.errorhandler(404) def not_found(error): return make_response(jsonify({'error':'Not Found'}),404) if __name__ == "__main__": app.run(debug = True)
在另一個terminal視窗執行: curl -i http://localhost:5000/example/api/v0.1/name/1233
輸出結果如下(結果在右邊):
當然API侷限在parse資料也太無聊了,所以要能添加與刪除資料吧
from flask import Flask, jsonify, make_response, abort app = Flask(__name__) data = [ { 'id':1233, 'name':u'Jason', 'description':u'handsome but impatient' }, { 'id':1234, 'name':u'Peter', 'description':u'tall and humorous' }, { 'id':1235, 'name':u'Henricks', 'description':u'Geek' } ] @app.route("/example/api/v0.1/name/<int:data_id>",methods = ['GET']) def get_data(data_id): people = [people for people in data if people['id'] == data_id ] if len(people) == 0: abort(404) return jsonify({'data':people[0]}) @app.errorhandler(404) def not_found(error): return make_response(jsonify({'error':'Not Found'}),404) #delete database data @app.route("/example/api/v0.1/name/<int:data_id>",methods = ['DELETE']) def delete_task(data_id): people = [people for people in data if people['id'] == data_id] if len(people) == 0: abort(404) data.remove(people[0]) return jsonify({'result' : True}) if __name__ == "__main__": app.run(debug = True)
在另一個terminal視窗執行:curl -i -H “Content-Type: application/json” -X DELETE -d ‘{“name”:”Jason”}’ http://localhost:5000/example/api/v0.1/name/1233
再次呼叫id 1233的話,就回傳沒有這筆資料了
POST資料
好了我們能刪除資料了,刪錯了怎麼辦??
用POST指令把它添加回去好了
from flask import Flask, jsonify app = Flask(__name__) data = [ { 'id':1233, 'name':u'Jason', 'description':u'handsome but impatient' }, { 'id':1234, 'name':u'Peter', 'description':u'tall and humorous' } ] @app.route("/example/api/v0.1/name/<int:data_id>",methods = ['GET']) def get_data(data_id): people = [people for people in data if people['id'] == data_id ] if len(people) == 0: abort(404) return jsonify({'data':people[0]}) @app.route("/example/api/v0.1/name",methods = ['POST']) def create_task(): if not request.json or not 'name' in request.json: abort(400) people = { 'id': data[-1]['id'] + 1, #id is default as the next id num 'name': request.json['name'], #name is a must 'description': request.json.get('description', ""), } data.append(people) return jsonify({'data': data}), 201 #return all data @app.errorhandler(404) def not_found(error): return make_response(jsonify({'error':'Not Found'}),404) if __name__ == "__main__": app.run(debug = True)
以上的api要求添加新的個人資料時,必須要有該資料的名字,如果沒有則回傳400錯誤。
執行一下指令就能添加一個名為DBlackKat的個人資料:
curl -i -H “Content-Type: application/json” -X POST -d ‘{“name”:”DBlackKat”}’ http://localhost:5000/example/api/v0.1/name
學會了怎麼添加那麼如何更改個人資料呢?
from flask import Flask, jsonify, make_response, abort, request app = Flask(__name__) data = [ { 'id':1233, 'name':u'Jason', 'description':u'handsome but impatient' }, { 'id':1234, 'name':u'Peter', 'description':u'tall and humorous' } ] @app.route('/todo/api/v1.0/tasks/<int:data_id>', methods=['PUT']) def update_task(data_id): people = [people for people in data if people['id'] == data_id] if len(people) == 0: abort(404) if not request.json: abort(400) if 'name' in request.json and type(request.json['name']) != unicode: abort(400) if 'description' in request.json and type(request.json['description']) is not unicode: abort(400) people[0]['name'] = request.json.get('name', people[0]['name']) people[0]['description'] = request.json.get('description', people[0]['description']) return jsonify({'result': people[0]}) if __name__ == "__main__": app.run(debug = True)
在另一個終端執行:
curl -i -H “Content-Type: application/json” -X PUT -d ‘{“name”:”Raymond”}’ http://localhost:5000/example/api/v0.1/name/1233
輸出結果如上,注意 Json 名字已經被更改成Raymond了
以上都是建立一個開放式的api, 如果今天想要使用認證才能登錄要怎麼辦呢?
Python 對於一切問題都有自己的library這裡我們就安裝 http_auth,
在同一個虛擬環境下執行 pip install http_auth
一下簡單介紹最基本的認證方式,如果是使用在產品上建議使用http_auth的flask網站上提到的範例,並且secret_key是由file讀取為佳。
from flask import Flask, jsonify, abort, make_response, request
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
data = [
{
'id':1233,
'name':u'Jason',
'description':u'handsome but impatient'
},
{
'id':1234,
'name':u'Peter',
'description':u'tall and humorous'
}
]
@auth.get_password
def get_password(username):
if username == 'theblackcat102':
return 'blablabla' #this is our password
return None
@auth.error_handler
def unauthorized(): #make unauthorised access return
return make_response(jsonify({'error': 'Unauthorised access'}), 403)
@app.route("/example/api/v0.1/name/<int:data_id>",methods = ['GET'])
@auth.login_required
def get_data(data_id):
people = [people for people in data if people['id'] == data_id ]
if len(people) == 0:
abort(404)
return jsonify({'data':people[0]})
@app.errorhandler(404)
@auth.login_required
def not_found(error):
return make_response(jsonify({'error':'Not Found'}),404)
#delete database data
@app.route("/example/api/v0.1/name/<int:data_id>",methods = ['DELETE'])
@auth.login_required
def delete_task(data_id):
people = [people for people in data if people['id'] == data_id]
if len(people) == 0:
abort(404)
data.remove(people[0])
return jsonify({'result' : True})
if __name__ == "__main__":
app.run(debug = True)
在另一個終端執行:
curl -u theblackcat102:blablabla -i http://localhost:5000/example/api/v0.1/name/1233
輸出結果如下:
如果密碼打錯了,結果就會出現我們設定的回饋(注意密碼打錯了):
參考來源: http://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask