API経由記事投稿機能の動作確認と404エラー(開発日記 No.054)
関連リンク
はじめに
昨日は、開発中のツールに組み込んでいる note.com API 連携機能について、認証方法を従来のメール/パスワード認証から Cookie 認証に変更しました。しかし、変更後の動作確認がうまくいかず、途中で作業を終えることになりました。
今日はその続きとして、変更した Cookie 認証方式での記事投稿機能が正しく動作するかを確認し、問題を解決することを目指します。
背景と目的
現在開発しているツールには、作成したコンテンツを自動で note.com に投稿する機能が必要です。そのために note.com の(非公式な)API を利用しています。昨日、より安定した連携を目指して認証方式を変更したため、その変更が意図通りに機能し、特に記事の「作成」と「更新」が行えるかを確認することが今回の目的です。
検討内容
まず、昨日の開発記録を読み返し、Cookie 認証への変更点や実装したテストコードの内容を再確認しました。認証に必要な Cookie 情報 (NOTE_AUTH_TOKEN
, NOTE_SESSION_V5
) は環境変数に設定済みで、テスト実行フラグ (TEST_USE_REAL_API
) も有効になっています。
準備は整っているはずでしたが、実際にテストを実行してみると、いくつかの問題点が明らかになりました。
-
API接続テストの失敗: 最初に、API への基本的な接続を確認するテストが
No valid authentication method
というエラーで失敗しました。これは、設定した Cookie 情報がリクエスト時に正しく利用されていない可能性を示唆しています。 -
記事作成テストの失敗: 次に、記事を作成するテストを実行したところ、
CSRF token not found
というエラーが発生しました。note.com のような Web サービスでは、不正なリクエストを防ぐために CSRF トークンが利用されることが一般的です。このエラーは、記事作成リクエストに必要な CSRF トークンを事前に取得できていないことを意味します。 - 記事更新テストの失敗: 記事作成が失敗するため、当然ながら既存の記事を更新するテストも失敗する状態でした。
これらの初期調査から、Cookie 認証情報の送信方法、または CSRF トークンの取得ロジックのいずれか、あるいは両方に問題があると推測し、修正作業に取り掛かりました。
実装内容
特定された問題を解決するために、以下の修正と試行錯誤を行いました。
-
Cookie認証の修正:
- Python の
requests
ライブラリで Cookie を送信する際、当初設定していたdomain="note.com"
指定が不要かもしれないと考え、削除しました。 - HTTP リクエストヘッダーに直接
Cookie
フィールドを設定する方法も試しました。 - よりブラウザからのリクエストに近づけるため、
Origin
ヘッダーやReferer
ヘッダーを追加してみました。
- Python の
-
CSRFトークン取得の改善:
- CSRF トークンは通常、記事編集画面などの HTML 内に含まれています。トークン取得を試みる対象ページを、当初の
/edit
から/new
へ、さらに note.com のトップページ (/
) へと変更し、どこかにトークンが含まれていないか探りました。 - HTML から特定のパターン(トークンらしき文字列)を抽出するために、正規表現を用いたバックアップ処理を追加しました。
- もし CSRF トークンが必須でなくなった可能性も考慮し、トークンなしで記事作成リクエストを送信するパターンも試しました。
- CSRF トークンは通常、記事編集画面などの HTML 内に含まれています。トークン取得を試みる対象ページを、当初の
-
API呼び出しの変更:
- note.com の API はバージョン管理されている可能性があるため、記事作成のエンドポイントを
/api/v1/notes
と/api/v2/notes
で切り替えて試しました。 - リクエストの形式(JSON ボディの内容など)を微調整しました。
- エラー発生時の詳細な情報を得るために、エラーハンドリング処理を強化しました。
- note.com の API はバージョン管理されている可能性があるため、記事作成のエンドポイントを
技術的なポイント
これらの地道な修正と試行錯誤の結果、Cookie 認証自体は正しく機能するようになりました。具体的には、API への接続を確認するテスト (test_api_availability
) や、ログイン中のユーザーの記事一覧を取得するテスト (test_user_notes_retrieval
) は成功するようになりました。これは、送信した Cookie 情報によってセッションが確立され、少なくとも一部の読み取り系の API は正常に呼び出せていることを示しています。
しかし、最も重要だった記事作成 (test_create_draft
) と記事更新 (test_update_draft
) のテストは、依然として失敗するままでした。最終的に表示されたエラーメッセージは以下の通りです。
ERROR scripts.clients.note_client:note_client.py:375 Error creating note: 404 Client Error: Not Found for url: https://note.com/api/v1/notes
この 404 Not Found
エラーは、リクエスト先の URL (https://note.com/api/v1/notes
) が存在しない、つまり、指定した API エンドポイントが見つからないことを意味します。以前はこのエンドポイントで記事作成ができていたはずなので、これは note.com 側で API の仕様が変更された(エンドポイントが変更された、あるいは廃止された)可能性が高いことを示唆しています。もちろん、認証方式(CSRF トークンの必要性や検証方法など)が変更された可能性も完全には否定できません。
所感
いやー、なかなか一筋縄ではいきませんね。Cookie 認証が通って、自分の記事一覧は取得できるようになったのに、肝心の記事作成が 404
エラーで弾かれてしまうとは…。最初は自分のコードのバグを疑って、Cookie の設定方法や CSRF トークンの取得方法をあれこれ試行錯誤していたのですが、どうやら問題はもっと根深いところ、つまり note.com の API 仕様そのものにある可能性が高そうです。
非公式な API を利用する以上、こういう仕様変更のリスクは常に覚悟していましたが、実際に直面するとやはり少し凹みますね。ただ、闇雲にコードを修正するのではなく、エラーメッセージ(特に 404
)から原因を推測し、API 側の変更の可能性にたどり着けたのは良かった点だと思います。地道なデバッグと切り分け作業が、少しずつ問題の本質に近づけてくれている感覚はあります。このもどかしさをバネにして、次の調査に進みたいと思います。
今後の課題
この 404 Not Found
エラーの真の原因を突き止め、記事投稿機能を復活させるために、以下のステップで調査を進める予定です。
- ブラウザ開発者ツールでのAPI調査: 実際に Chrome などのブラウザで note.com にログインし、手動で記事を作成・保存する操作を行います。その際のネットワークリクエストを開発者ツールで監視し、どの API エンドポイントが、どのようなヘッダーやボディで呼び
Discussion