WordPressの記事をREST APIで取得し、Googleスプレッドシートで選別して、ポートフォリオサイトに反映する仕組みを構築しました

はじめに

現在開発中の「My Portfolio」の技術ブログ一覧ページで、「WordPress同期」ボタンを押せば、

以前、WordPressで書いた技術ブログのデータが同期されるようにしました。

↓ 同期後にサクセスメッセージを表示させています。

WordPress REST APIとは

WordPress REST APIとは、WordPressの記事データをJSON形式で取得するための仕組みです。

プログラムから記事情報を取得できるため、今回のようにWordPressの記事を別のシステムへ取り込む際に利用できます。

全体の処理の流れ

全体の処理の流れは以下のとおりです。

  1. ローカル環境でWordPress同期ボタンを押す
  2. /blogs/import-wordpress にPOSTリクエストが送られる
  3. 事前に用意したGoogleスプレッドシートから技術ブログの記事URLを取得する
  4. それぞれのURLからslugを取り出す
  5. slugを使用してWordPress REST APIで記事情報を取得する
  6. WordPressの記事データを整形する
  7. DBに存在する記事なら更新する
  8. DBに存在しない記事なら新規登録する
  9. WordPress側に存在しない記事はDBから削除する
  10. 新規・更新・削除・スキップ件数をURLパラメータで返す

1. ローカル環境でWordPress同期ボタンを押す

技術ブログの一覧ページにあるWordPress同期ボタンを押します。

http://127.0.0.1:8000/blogs-page

このボタンは本番環境では表示されません。

https://github.com/ki-hi-ro/my-portfolio/blob/main/app/templates/blogs.html

is_productionは、一覧ページ取得処理でテンプレートに渡されています。

https://github.com/ki-hi-ro/my-portfolio/blob/main/app/routers/blogs.py

本番環境の時、is_productionがTrueになります。

そのため、not is_productionがFalseになります。

つまり、WordPress同期のボタンが表示されなくなります。

2. /blogs/import-wordpress にPOSTリクエストが送られる

以下のフォームを指定しているので、/blogs/import-wordpressにPOSTリクエストが送られます。

ルーターで、POSTリクエストを受け取っています。

受け取った後に、import_wordpress関数の処理が始まります。

/blogs/は、prefixとして指定しています。

tagsは、Swaggerの見た目・ドキュメント整理のための設定です。

Swaggerは、APIをブラウザで試せるというFastAPIの機能です。

http://127.0.0.1:8000/docs でアクセス可能です。

3. 事前に用意したGoogleスプレッドシートから技術ブログ対象の記事URLを取得する

事前に、Googleスプレッドシートでリストを作成しておきました。

これは、私がこれまでに書いた記事をMy Portfolioのコンテンツ作成のために分類したものです。

そして、CSV形式のgoogleスプレッドシートの公開URLを作成します。

ファイル > 共有 > ウェブへの公開で作成できます。

こちらのURLは、get_tech_blog_urls_from_sheet関数でsheet_csv_urlに代入します。

pandasのread_csv関数で、このCSVを読み込んでdfに代入します。

dfから技術ブログの列が◯の行がTrueの行を抽出して、tech_blogsに代入します。

tech_blogsの中身は、以下のようなイメージです。

記事URL制作物技術ブログ職務経歴
https://ki-hi-ro.com/design/
https://ki-hi-ro.com/post-output/
https://ki-hi-ro.com/custom-field/

ここから記事URLの列を抽出して、空白を削除して、リストにします。

target_urlsに、Googleスプレッドで抽出された技術ブログの記事URLのリストが代入されます。

4. それぞれのURLからslugを取り出す

対象の記事URLのリストが代入されたtarget_urlsを使用して処理を行います。

get_slug_from_url関数を使用してslugを取得します。

この関数の定義はこちらです。

対象記事のURLを解析した後のイメージは以下です。

pathの最後の/を取り除くと「/design」のようになります。

“/” で分割して作成したリストの最後の英単語を取得したものを返します。

WordPress REST APIでは、記事を slug で検索できます。

例えば、

デザイン4原則

という記事URLの場合、

slug は design になります。

そのため、URLから slug を取り出して、
後続の WordPress REST API の検索に利用しています。

5. slugを使用してWordPress REST APIで記事情報を取得する

requestsのget関数で、記事情報を取得します。

base_urlは、WordPress REST APIのURLを指定します。

投稿情報のJSONのリストが入っています。

slugは、「4. 各URLからslugを取り出す」で取得しました。

headersでは、requestに渡すヘッダーを定義します。

それぞれの意味は以下です。

項目意味
keyUser-Agentブラウザなどのアクセスしてきたクライアント
valueMozilla/5.0今回はサーバーからのBot対策を回避するため、ブラウザっぽい Mozilla/5.0という名前を指定

項目意味
keyAcceptどんな形式のレスポンスを受け取れるか
valueapplication/json,text/html,*/*JSON, HTML, なんでも

項目意味
keyRefererどのページから来たか
valuehttps://ki-hi-ro.com/私のブログ

取得した値は、responseに代入します。

ステータスコードが正常ではない場合は、処理を中断して、次のURLの処理に進みます。

JSONをPythonのデータに変換します。

記事が存在しない場合はスキップします。

6. WordPressの記事データを整形する

WordPress REST APIは検索結果をリスト形式で返します。

今回の処理ではslugを指定しているので、リストには一つしか要素がありません。

そのため、posts[0]で最初の記事データを取り出しています。

postからtitleとblog_urlとcontentとsummaryとpublished_atとtagsを取得します。

postには、以下のようなJSONが入っているため、

{
  "title": {
    "rendered": "記事タイトル"
  },
  "link": "https://ki-hi-ro.com/design/"
}

post[“title”][“renderd”]でタイトルを取得しています。

7. DBに存在する記事なら更新する

DBのURLとWordPressから取り込んだURLを比較して、一致した場合、タイトルなどを更新します。

updatedは、for文の前で初期化しています。

8. DBに存在しない記事なら新規登録する

DBに存在しない場合は、blogで登録します。

importedは、updateと同様に、for文の前で初期化しています。

9. WordPress側に存在しない記事はDBから削除する

wp_urlsがあれば、wp_urlsにないDB側のurlをフィルタリングして、deleteで削除します。

delete関数は、削除した件数を返します。

10. 同期結果をURLパラメータで返す

最後に、同期結果をURLパラメータとして /blogs-page に渡しています。

imported には新規登録件数、
updated には更新件数、
deleted には削除件数、
skipped にはスキップ件数が入ります。

これにより、同期後の一覧画面で「何件追加・更新・削除・スキップされたか」を確認できます。

まとめ

今回は、WordPress REST APIで取得した記事データを、自作ポートフォリオサイトのDBに同期する仕組みを実装しました。

Googleスプレッドシートで対象記事を管理し、WordPress REST APIから記事情報を取得し、DBに存在する記事は更新、存在しない記事は新規登録、WordPress側に存在しない記事は削除するようにしました。

単に記事を取得するだけではなく、外部サービスのデータを自作アプリケーションに取り込み、同期状態を管理する処理を作れたのが大きな学びでした。

今回作成した仕組みによって、
WordPressで技術ブログを書くだけで、
My Portfolio側へ同期できるようになりました。

これにより、コンテンツ管理の手間を減らしながら、
ポートフォリオサイトの情報を最新の状態に保てるようになりました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です