この記事は3年以上前に書かれた記事で内容が古い可能性があります
flaskでAPIサーバを作成する
flaskでAPIサーバを作成してみる
今回は、TwitterIDから、最近呟いた地名を取得するAPIを作成する
MeCabなど環境作成はサクッとAmazon LinuxにMecab導入を参考にしてください
【APIサーバ】flask-corsをインストール
# pyenv versions system * 3.5.0 (set by /root/.python-version) # pip install requests requests_oauthlib # pip install flask-cors # pip freeze certifi==2018.1.18 chardet==3.0.4 click==6.7 Flask==0.12.2 Flask-Cors==3.0.3 idna==2.6 itsdangerous==0.24 Jinja2==2.10 MarkupSafe==1.0 mecab-python3==0.7 netifaces==0.10.6 oauthlib==2.0.6 requests==2.18.4 requests-oauthlib==0.8.0 six==1.11.0 urllib3==1.22 Werkzeug==0.14.1
【APIサーバ】各スクリプトの配置
最新版はこちら(https://github.com/yoshi-island/mecab-twitter-api)
「get_tweets_place_list.py」で、tweetを取得してMecabで地名を抽出、
「mecab-twitter-api.py」で、APIサーバとしてリクエストが来たら返信する
passwords.py
Twitter tokenは一応別ファイルに書いておいて、モジュールとして呼び出す。
Twetterの設定はこちらを参考に。
twitter botを作ってみた
passwords.py
oath_keys = { "consumer_key": "", "consumer_secret": "", "access_token": "", "access_token_secret": "" }
get_tweets_place_list.py
get_tweets_place_list.py
#!/usr/bin/env python # -*- coding:utf-8 -*- # python 3.5.0 ################### # usage ################### # #user = "<tweetuser>" #place_list_rank = get_tweets_place_list(user) # # passwords.py # oath_keys = { # "consumer_key": "", # "consumer_secret": "", # "access_token": "", # "access_token_secret": "" # } ################### # import modules ################### from requests_oauthlib import OAuth1Session import json import MeCab import collections import passwords ################### # variables ################### oath_keys = passwords.oath_keys ################### # create oath session ################### def session_create(oath_keys): oath = OAuth1Session( oath_keys["consumer_key"], oath_keys["consumer_secret"], oath_keys["access_token"], oath_keys["access_token_secret"] ) return oath ################### # get tweets ################### def get_tweets(user,oath): user = user url = "https://api.twitter.com/1.1/statuses/user_timeline.json?" params = { "screen_name": user, "count": "1000" } oath = oath responce = oath.get(url, params = params) if responce.status_code != 200: print("Error code: %d" %(responce.status_code)) return None tweets = json.loads(responce.text) #tweets_format = json.dumps(tweets, indent=4, separators=(',', ': ')) #print(tweets_format) tweets_text_list = "" for l in tweets: tweets_text_list += l['text'] + "\n" return tweets_text_list ################### # mecab_analyze_tweets ################### def mecab_analyze_tweets(tweets_text_list): tweets_text_list = tweets_text_list.split("\n") mecab = MeCab.Tagger("-Ochasen") place_list = [] place_list_srctwt = [] for l in tweets_text_list: if len(l) > 0: mecab_parsed = mecab.parse(l) items = mecab_parsed.split("\t") if len(items)>4: if items[3].find("地域") > -1: if len(items[0]) > 1: if items[0] != "日本": place_list.append(items[0]) place_list_srctwt.append(l) count_dict = collections.Counter(place_list) place_list_rank = count_dict.most_common(10) return place_list_rank,place_list_srctwt ################### # main ################### #if __name__ == "__main__": def get_tweets_place_list(user): oath = session_create(oath_keys) tweets_text_list = get_tweets(user,oath) # list place_list_rank,place_list_srctwt = mecab_analyze_tweets(tweets_text_list) # list return place_list_rank, place_list_srctwt
mecab-twitter-api.py
mecab-twitter-api.py
#!/usr/bin/env python # -*- coding:utf-8 -*- # python 3.5.0 ################### # import modules ################### import get_tweets_place_list from flask import Flask, jsonify, abort, make_response import netifaces import json from flask_cors import CORS, cross_origin import ssl ################### # get local address ################### sv_ip = netifaces.ifaddresses('eth0')[netifaces.AF_INET][0]['addr'] ################### # api functions ################### api = Flask(__name__) CORS(api) api.config['JSON_AS_ASCII'] = False # for Japanese language context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.load_cert_chain('<cert path>', '<key path>') @api.route('/getTweetsPlace/<string:userId>', methods=['GET']) def get_user(userId): user = userId try: place_list_rank, place_list_srctwt = get_tweets_place_list.get_tweets_place_list(user) # error judge place_name = place_list_rank[0][0] # data existance judge place_cnt = place_list_rank[0][1] # data existance judge except: return make_response(jsonify({'error': 'Not found'}), 404) rank_list = [ { "number": 1, "place": place_name, "count": place_cnt }] for i in range (2,6): place_name = "" place_cnt = "" try: place_name = place_list_rank[i][0] place_cnt = place_list_rank[i][1] component = { "number": i, "place": place_name, "count": place_cnt } rank_list.append(component) except: break result = { "result":True, "data":{ "userId":user, "rank":rank_list, "src_place_twt": place_list_srctwt } } return make_response(jsonify(result)) @api.after_request def after_request(response): response.headers.add('Access-Control-Allow-Origin', '*') response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization') response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS') return response @api.errorhandler(404) def not_found(error): return make_response(jsonify({'error': 'Not found'}), 404) if __name__ == '__main__': api.run(host=sv_ip, port=3000, ssl_context=context, threaded=True, debug=True)
【Mac】実行
ローカルMacから実行
今回はホリエモンのIDを利用
https://{API IP}:3000/getTweetsPlace/@{TwitterID}
きちんと返って来ている
% curl -k https://{API IP}:3000/getTweetsPlace/@takapon_jp { "data": { "rank": [ { "count": 1, "number": 1, "place": "押尾" }, { "count": 1, "number": 2, "place": "大阪" }, { "count": 1, "number": 3, "place": "藤沢" }, { "count": 1, "number": 4, "place": "心斎橋" } ], "src_place_twt": [ "エジプト古代人!", "藤沢数希さん(@kazu_fujisawa)のぼく愛もそう…", "押尾紗季プロ❣️", "心斎橋駅から徒歩1分です!", "大阪府 大阪市中央区 西心斎橋1-9-31 辻本ビル 4階" ], "userId": "@takapon_jp" }, "result": true }
Trouble Shooting
以下のようなエラーが出たので
The 'Access-Control-Allow-Origin' header has a value 'null' that is not equal to the supplied origin. Origin 'null' is therefore not allowed access.
以下を参考に、「@api.after_request」を追加したら、解消した
https://stackoverflow.com/questions/22181384/javascript-no-access-control-allow-origin-header-is-present-on-the-requested
@api.after_request def after_request(response): response.headers.add('Access-Control-Allow-Origin', '*') response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization') response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS') return response