概要
Qiita APIが便利でよく利用しているのですが、毎回curl
やスクリプトを組むのが面倒だったので、CLIツールを作ってみました。何番煎じか数えるのはやめましたw
利用イメージ
インストール方法
さくっと作ったので、PyPiへの登録はしていません。GitHubからソースを取得してインストールします。
> git clone https://github.com/kai-kou/qiita-py-cli.git > cd qiita-py-cli > pip install -r requirements.txt > python setup.py install # ターミナルの再起動(bash) > exec $SHELL -l # ターミナルの再起動(fish) > exec fish -l
アンインストールする場合は、以下のようにします。
> python setup.py install --record files.txt > cat files.txt | xargs rm -rf
以下の記事を参考にさせてもらいました。
setup.pyを用いてインストールしたモジュールのアンインストール方法
https://qiita.com/orion46/items/dfe476067e499cca8535
使い方
Qiitaのアクセストークンが必要となります。アクセストークンはQiitaに認証していると以下のURLから取得できます。
https://qiita.com/settings/tokens/new
POST系のコマンドを利用する場合にはスコープのwrite_qiita
が必要になります。情報取得だけで利用するのなら、read_qiita
があれば十分です。
取得できたらqiita init
コマンドでアクセストークンを設定します。
# アクセストークンの設定 > qiita init Qiitaのアクセストークンを入力してください:
環境変数にアクセストークンを設定することもできます。
# bash > export QIITA_PY_CLI_ACCESS_TOKEN=<Qiitaのアクセストークン> # fish > set -x QIITA_PY_CLI_ACCESS_TOKEN <Qiitaのアクセストークン>
アクセストークンが設定できたらコマンドを実行してみます。
> qiita get_user kai_kou {"description": "2004-2011 フリーランス。2011-2018 株式会社グリーティングワークスでEC、バックヤード開発をプレイングマネージャーとしてAWSを超積極的に導入。サーバレス大好きっ子。Python、Ruby、TypeScript、C#とかが好み。2018/7からCloudpackにJoin。\r\n\r\nQiita記事は誰かひとりの琴線に触れたらそれでいい^^", "facebook_id": "kokaorz", "followees_count": 429, "followers_count": 79, "github_login_name": "kai-kou", "id": "kai_kou", "items_count": 79, "linkedin_id": "", "location": "Osaka, Japan", "name": "甲斐 甲", "organization": "アイレット株式会社", "permanent_id": 48549, "profile_image_url": "https://qiita-image-store.s3.amazonaws.com/0/48549/profile-images/1524132209", "twitter_screen_name": "k_aik_ou", "website_url": "https://twitter.com/k_aik_ou"}
取得結果はJSONとなりますので、jq
コマンドなどで整形する前提です。
> qiita get_user kai_kou | jq { "description": "2004-2011 フリーランス。2011-2018 株式会社グリーティングワークスでEC、バックヤード開発をプレイングマネージャーとしてAWSを超積極的に導入。サーバレス大好きっ子。Python、Ruby、TypeScript、C#とかが好み。2018/7からCloudpackにJoin。\r\n\r\nQiita記事は誰かひとりの琴線に触れたらそれでいい^^", "facebook_id": "kokaorz", "followees_count": 429, "followers_count": 79, "github_login_name": "kai-kou", "id": "kai_kou", "items_count": 79, "linkedin_id": "", "location": "Osaka, Japan", "name": "甲斐 甲", "organization": "アイレット株式会社", "permanent_id": 48549, "profile_image_url": "https://qiita-image-store.s3.amazonaws.com/0/48549/profile-images/1524132209", "twitter_screen_name": "k_aik_ou", "website_url": "https://twitter.com/k_aik_ou" }
jq
コマンドについては下記が参考になります。
jq コマンドを使う日常のご紹介
https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af
実装
コマンドラインパーサー
パラメータ設定はdocoptを利用しています。パーサーを自動的に作成してくれるので、お手軽です。メソッド名をいちいち書くのが面倒だったので、下記を参考にメソッドを洗い出して、必要なものだけを記載するようにしました。パラメータは、、、自力でコツコツと。。。
Python: オブジェクトのメソッド一覧を取得する
https://qiita.com/suin/items/b15f908aaf8023a8a1fc
実装の一部抜粋
def main(): _USAGE = ''' Qiita API CLI Usage: qiita init qiita create_access_token [--params=<kn> --headers=<kn>] qiita create_item [--params=<kn> --headers=<kn>] qiita create_item_comment <item_id> [--params=<kn> --headers=<kn>] qiita delete_access_token <token> [--params=<kn> --headers=<kn>] qiita delete_comment <id> [--params=<kn> --headers=<kn>] qiita delete_item <id> [--params=<kn> --headers=<kn>] qiita follow_tag <id> [--params=<kn> --headers=<kn>] qiita follow_user <user_id> [--params=<kn> --headers=<kn>] qiita get_authenticated_user [--params=<kn> --headers=<kn>] qiita get_authenticated_user_items [--params=<kn> --headers=<kn>] qiita get_comment <id> [--params=<kn> --headers=<kn>] qiita get_item <id> [--params=<kn> --headers=<kn>] qiita get_item_stock <item_id> [--params=<kn> --headers=<kn>] qiita get_tag <id> [--params=<kn> --headers=<kn>] qiita get_tag_following <id> [--params=<kn> --headers=<kn>] qiita get_user <id> [--params=<kn> --headers=<kn>] qiita get_user_following <user_id> [--params=<kn> --headers=<kn>] qiita list_item_comments <item_id> [--params=<kn> --headers=<kn>] qiita list_item_stockers <item_id> [--params=<kn> --headers=<kn>] qiita list_items [--params=<kn> --headers=<kn>] qiita list_tag_items <id> [--params=<kn> --headers=<kn>] qiita list_tags [--params=<kn> --headers=<kn>] qiita list_user_followees <user_id> [--params=<kn> --headers=<kn>] qiita list_user_followers <user_id> [--params=<kn> --headers=<kn>] qiita list_user_following_tags <user_id> [--params=<kn> --headers=<kn>] qiita list_user_items <user_id> [--params=<kn> --headers=<kn>] qiita list_user_stocks <user_id> [--params=<kn> --headers=<kn>] qiita list_users [--params=<kn> --headers=<kn>] qiita stock_item <item_id> [--params=<kn> --headers=<kn>] qiita unfollow_tag <id> [--params=<kn> --headers=<kn>] qiita unfollow_user <user_id> [--params=<kn> --headers=<kn>] qiita unstock_item <item_id> [--params=<kn> --headers=<kn>] qiita update_comment <id> [--params=<kn> --headers=<kn>] qiita update_item <id> [--params=<kn> --headers=<kn>] Options: --help ヘルプを表示 --params=<kn> params [default: None] --headers=<kn> headers [default: None] ''' all_params = docopt(_USAGE)
docopt
http://docopt.org/
Pythonのdocopt使い方メモ
https://qiita.com/ymdymd/items/651245d80964393b12c5
PythonでCLIツールを作成するのにdocoptでパラメータのパーサー作成を自動化する
https://cloudpack.media/44225
Qiita APIへのアクセス
下記で紹介されているラッパーを利用させてもらいました。一部APIの実装が足りていなかったので、フォークしました。
Qiita API v2のPythonラッパー実装した
https://qiita.com/petitviolet/items/deda7b66852635264508
kai-kou/qiita_py: Python Wrapper for Qiita API v2
https://github.com/kai-kou/qiita_py
基本的にはラッパーで実装されているメソッドをパラメータとして引き渡し実行しているだけです。お手軽!
実装の一部抜粋
command = [k for k, v in all_params.items() if v == True] params = [ v for k, v in all_params.items() if re.match(r'\<.*\>', k) and v is not None] options = [ json.loads(v) for k, v in all_params.items() if re.match(r'^\-', k) and v != 'None'] params.extend(options) (略) client = QiitaClient(access_token=access_token) res = getattr(client, command[0])(*params)
getattr
を利用して、メソッドを動的に呼んでいます。下記が詳しく参考になりました。
pythonで動的にクラスとメソッドをCallする
https://yuji0602.hatenablog.jp/entry/2018/03/21/225700
まとめ
CLIツールを初めて作ってみましたが、便利なライブラリが充実しているので、とても簡単に実装することができました。
さくっと実装したので、テストも書いてない状態なので、テストを書いたらPyPiに登録してみたいと思います^^
参考
docopt
http://docopt.org/
Pythonのdocopt使い方メモ
https://qiita.com/ymdymd/items/651245d80964393b12c5
Qiita API v2のPythonラッパー実装した
https://qiita.com/petitviolet/items/deda7b66852635264508
Pythonにおけるリフレクション
https://qiita.com/icoxfog417/items/bf04966d4e9706eb9e04
pythonで動的にクラスとメソッドをCallする
https://yuji0602.hatenablog.jp/entry/2018/03/21/225700
Python: オブジェクトのメソッド一覧を取得する
https://qiita.com/suin/items/b15f908aaf8023a8a1fc
Python: PyPI にないパッケージを依存パッケージにするには
https://blog.amedama.jp/entry/2016/02/18/221555
Pythonで関数の引数にリスト、タプル、辞書を展開して渡す
https://note.nkmk.me/python-argument-expand/
Pythonでリストとタプルを相互に変換するlist(), tuple()
https://note.nkmk.me/python-list-tuple-convert/
Pythonで対応する値に基づいて辞書型のキーをフィルターしたい
https://teratail.com/questions/3731
Python Prompt Toolkitで対話的な選択コマンドを作る
https://vaaaaaanquish.hatenablog.com/entry/2017/12/25/183927
Pythonでyamlファイルを設定ファイルとして使う
http://www.bokupy.com/detail/74
pythonでホームディレクトリの取得
https://qiita.com/sotetsuk/items/d7b32b12f94a341c79a5