はじめに
この記事はUdon Advent Calendar 2025 - Adventarの1日目の記事です。
Udon Advent Calendar開催
去年に引き続き今年も開催することにしました。
技術記事はQiitaに、それ以外ははてなブログに投稿しようと思っています。よろしくお願いします。
ブログの投稿をコマンドで
さて、アドベントカレンダーをやっていくわけですが、アドベントカレンダーの投稿を作成するときはブログサイトで記事を作らなくてはいけません。
記事投稿ページに直書きすることは少ないと思います。大抵は手元のエディタで文章を作成し、完成したらそれを投稿ページにコピペして投稿する、という流れだと思います(VSCodeなどにはそのまま投稿できる拡張機能があったりしますが)。
しかし、この作業はいささか面倒な時があります。ウィンドウを移動しなくてはならないし、手動操作が介在しています。
というわけで今回は、コマンドラインからブログの記事を投稿する方法をまとめていこうと思います!
この記事は前編・後編の構成とします!後編は12/5の枠にする予定なのでお楽しみに!
cURLコマンド
「ブログに記事を投稿する」という操作は一種の通信です。この通信をコマンドを使って実行することができればいいわけです。
というわけで今回は、「cURL」を用いてみようと思います。
このコマンドはLinuxなどでよく使われるもので、簡単に言うと様々なプロトコルを用いて指定したURLとの通信を行うものです。
多様なオプションがあり、以下のようなことができます。
- レスポンスの取得
- ファイルのダウンロード
- ファイルのアップロード
参考:https://e-words.jp/w/cURL.html
他にもいろいろなことができるコマンドですが、今回はHTTPのPOSTメソッドを使うためにこのコマンドを用いてみようと思います。
APIリファレンスを参考にやってみよう
公開されているAPIはそのシステムの窓口であり、正当なリクエストを受け取るとそれに応じた答えを返してくれます。このリクエストの送信のためにcurlコマンドを用いるわけですが、「正当な」リクエストをどのように作ればいいかはシステムによって違います。
各ブログサイトのAPIリファレンスを確認してみると、curlでどのように書くとよいのかということが記述されています。これを参考にしましょう。
公式APIリファレンスに「新たに記事を作成します。」というところがあったのでこれを参考にします。
とりあえずアクセストークンが必要なので、それを取得しましょう。ここからトークンを発行します。必要なスコープはwrite_qiitaです。
それでもって、curlコマンドを以下のように設定します。
curl -v -X POST "https://qiita.com/api/v2/items" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer [アクセストークン]" \
-d '{
"body": "# Example",
"private": true,
"tags": [
{
"name": "Ruby",
"versions": [
"0.0.1"
]
}
],
"title": "Example title",
}'
肝はjsonを仕込んでいる-dオプションの所ですね。上からパラメータを説明すると、
-
body:記事本文(マークダウン) -
private:公開するか -
tags:つけるタグ(versionsは消しても大丈夫らしいです) -
title:記事のタイトル
これを実行したところ、以下のような記事を投稿することができました。
また、実行に成功すると以下のようなjson形式のデータが返ってきます。
{"rendered_body":" ...
マークダウン形式で記事を書き、それをcurlコマンドに入れ込めば、コマンドラインからQiitaの記事を投稿することができるはずです。
ただ、いちいちcurlコマンドを成型するのは面倒です。トークンの管理もしなくてはいけません。というわけで、プログラムに指示をし、自動で成型・実行してもらうことにしましょう!
cURL実行用プログラムの作成
というわけで、post_to_qiita_with_curl.pyというPythonプログラムを作成しました。
import os
import json
import dotenv
# ファイルの読み込み
def read_file(file_path: str) -> str:
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
# リクエスト用jsonの成型
def build_json_body(post_content: str, info_json: dict) -> str:
body = {
"body": post_content,
"private": info_json["private"],
"tags": info_json["tags"],
"title": info_json["title"],
}
return json.dumps(body)
# curlコマンドの成型
def make_curl_command(token: str, post_content: str, info_json: str) -> str:
curl_command = (
f"curl -X POST https://qiita.com/api/v2/items "
f'-H "Authorization: Bearer {token}" '
f'-H "Content-Type: application/json" '
f"-d '{build_json_body(post_content, info_json)}'"
)
return curl_command
def main():
token = os.getenv("QIITA_TOKEN")
post_content = read_file(
os.path.join(os.path.dirname(__file__), "..", "data", "post.md")
)
info_json = json.loads(
read_file(
os.path.join(os.path.dirname(__file__), "..", "data", "qiita_info.json")
)
)
curl_command = make_curl_command(token, post_content, info_json)
os.system(curl_command)
if __name__ == "__main__":
dotenv.load_dotenv(os.path.join(os.path.dirname(__file__), "..", ".env"))
main()
マークダウンファイルおよび投稿情報のjsonファイルを読み込み、適切にcurlコマンドを作ってからそれを実行するという流れです。
jsonファイルの中身は以下のようになっています。上記のcurl例からbodyのみを省いた形ですね。
{
"private": true,
"tags": [
{
"name": "Ruby",
"versions": [
"0.0.1"
]
}
],
"title": "Example title"
}
.envファイルは以下のようにします。
QIITA_TOKEN = "sample_token_value"
実行
実行の際、ディレクトリ構成は以下のようにします。
.
├── .env
├── data/
│ ├── post.md
│ └── qiita_info.json
└── src/
└── post_to_qiita_with_curl.py
実行方法は以下の通りです。
-
.envにトークンを記入する -
post.mdに記事の内容をコピペする -
qiita_info.jsonの内容を書き換える -
post_to_qiita_with_curl.pyを実行する
これによって、作成した記事を投稿することができます!実行すると以下のような感じになります。
$ python3 -u ./src/post_to_qiita_with_curl.py
{"rendered_body":" ...
このプログラムはこのリポジトリに置きました。クローンすると使えるはずなので是非やってみてください!
おわりに
コマンドラインからブログの記事を投稿することができました。この記事もコマンドラインから投稿したものです。
定期実行するプログラムを別で組んでこのコマンドを組み込めば、ストックした投稿を決まった時間に投稿する、なんてこともできそうです。これで投稿忘れも安心ですね。
それではまた、明日の記事でお会いしましょう!