0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WindowsタスクスケジューラとPythonで実現するZenn記事の全自動定期投稿パイプライン

0
Posted at

はじめに

AIエージェントや個人の執筆によって蓄積された技術記事ストックを、手動で1本ずつQiitaやZennへデプロイしていく作業は、時として手間や投稿漏れの原因になります。

特にZennのGitHub連携機能を活用している場合、リポジトリにMarkdownを追加して git push するだけで自動公開できますが、「指定した日時に1本ずつ定期投稿したい」「手動操作なしで自動化したい」 というニーズが存在します。

本記事では、Windows環境の タスクスケジューラ(schtasksPythonスクリプト を組み合わせ、ローカルのMarkdownストックから1日1投稿のペースで Zenn-for-me リポジトリへ記事をデプロイ・git push・アーカイブ化する完全自動運用パイプラインの構築手法を解説します。


1. 自動投稿パイプラインのアーキテクチャ

システム全体は以下のコンポーネントで構成されます。

[ Obsidian / ローカル技術記事ストック ]
          │ (未公開記事: published: false)
          ▼
[ Python自動パブリッシュスクリプト (publish.py) ]
          │ 1. 最古の未公開記事をピックアップ
          │ 2. Zenn用 frontmatter (published: true) へ変更
          │ 3. C:\Projects\Zenn-for-me\articles\ へコピー
          │ 4. git add . && git commit && git push
          │ 5. 元記事を C:\Obsidian\技術記事\公開済み\ へアーカイブ
          ▼
[ Windows タスクスケジューラ (schtasks) ] ── (毎日 09:00 AM に自動起動)
          ▼
[ Zenn (GitHub連携自動デプロイ) ]

2. Zennにおける自動投稿ペースと制限の検証

自動投稿化にあたり懸念されるのが、API制限やスパム判定等のハード/ソフト制限です。

Zennの標準的な運用およびGitHub連携の仕様上、1日1投稿〜2投稿 程度のペースであれば、通常の執筆活動としてみなされ、制限に抵触することはありません。

本パイプラインでは安全性を最優先し、「1日1投稿」 の一定ペースでWindowsタスクスケジューラから同期処理をトリガーする設計としています。


3. Pythonによる自動パブリッシュスクリプトの実装

以下は、ストックディレクトリから記事を選択し、Zenn用リポジトリへ同期・git push を行うPythonスクリプトの核となる実装例です。

import os
import shutil
import subprocess
from pathlib import Path
import re

STOCK_DIR = Path(r"C:\Obsidian\技術記事")
ZENN_REPO_DIR = Path(r"C:\Projects\Zenn-for-me")
PUBLISHED_DIR = STOCK_DIR / "公開済み"

def publish_next_article():
    # 1. ストックディレクトリ内の未公開Markdownを取得
    articles = [f for f in STOCK_DIR.glob("*.md") if f.is_file()]
    if not articles:
        print("[INFO] 投稿対象の未公開記事はありません。")
        return

    target_article = articles[0]  # 最古の記事を対象
    print(f"[INFO] 投稿対象記事: {target_article.name}")

    # 2. 本文の published: false を published: true に書き換え
    content = target_article.read_text(encoding="utf-8")
    updated_content = re.sub(r"published:\s*false", "published: true", content)

    # 3. Zennリポジトリの articles フォルダへ保存
    dest_path = ZENN_REPO_DIR / "articles" / target_article.name
    dest_path.write_text(updated_content, encoding="utf-8")

    # 4. Git Push の実行
    try:
        subprocess.run(["git", "add", "."], cwd=ZENN_REPO_DIR, check=True)
        subprocess.run(
            ["git", "commit", "-m", f"auto-publish: {target_article.stem}"],
            cwd=ZENN_REPO_DIR,
            check=True
        )
        subprocess.run(["git", "push", "origin", "main"], cwd=ZENN_REPO_DIR, check=True)
        print("[SUCCESS] Git push に成功しました。")
    except subprocess.CalledProcessError as e:
        print(f"[ERROR] Git操作に失敗しました: {e}")
        return

    # 5. 公開済みフォルダへアーカイブ移動
    PUBLISHED_DIR.mkdir(exist_ok=True)
    shutil.move(str(target_article), str(PUBLISHED_DIR / target_article.name))
    print(f"[SUCCESS] アーカイブ完了: {PUBLISHED_DIR / target_article.name}")

if __name__ == "__main__":
    publish_next_article()

4. Windows schtasks を用いたタスク登録

管理者権限のコマンドプロンプトまたはPowerShellから schtasks コマンドを実行し、上記スクリプトを毎日定刻(例: 毎朝 9:00 AM)に自動実行させます。

タスク登録コマンドの例

schtasks /Create /TN "ZennAutoPublisher" /TR "poetry run python C:\Projects\Zenn-for-me\scripts\publish.py" /SC DAILY /ST 09:00 /F
  • /TN "ZennAutoPublisher": タスク名の指定
  • /TR "...": 実行するコマンドライン
  • /SC DAILY: 毎日実行のスケジュール
  • /ST 09:00: 実行時刻 (09:00 AM)
  • /F: 同名タスクが存在する場合の上書き

5. まとめ

  1. 手動デプロイからの解放: 記事ストックを置いておくだけで、タスクスケジューラとPythonが毎日自動でデプロイとアーカイブを完了してくれます。
  2. 投稿ペースの平滑化: 一度に大量投稿してインプレッションを拡散させるのではなく、1日1本ずつ安定してコンテンツを提供することが可能になります。
  3. Windows環境への最適化: WSLやLinuxサーバーを介さず、Windows標準機能である schtasks を活用することで、軽量かつ信頼性の高いローカル自動化が実現できます。

記事の執筆とデプロイを分離・自動化したい方は、ぜひこのパイプラインを参考にしてみてください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?