pythonでConfluenceAPI(v2)から記事の取得・更新をする

技術

こんにちは。ざわかける!のざわ(@zw_kakeru)です。
今回はConfluenceAPIを使って記事の取得、更新なんかをやってみようと思います。
pythonを使います。

前提

  • Confluenceにアクセスできる環境がある

公式ドキュメント

The Confluence Cloud REST API

APIトークンの作成

スクリプトからコンフルにアクセスするためのAPIトークンを発行します。
コンフル右上の自分のアイコンから設定を開いて、「パスワード」をクリックします。

するとセキュリティ画面が開くので、APIトークンをクリックします。

APIトークンが作成できます。

作成したAPIトークンはどこかにメモしておきましょう。

記事の取得

リクエストするためのpythonスクリプトを書きましょう。
ひとまず、pageIdを使って問い合わせ、ページの内容を入手してhtmlファイルを出力してみます。
まずは、内容を取得したいコンフルページを適当に作成します。

今回はこのページを例にAPIを使ってみます。
公式ドキュメントを参考にしつつ、API v2形式で記述します。
ページ内容の入手はいくつか方法がありますが今回はGet page by id を使ってみましょう。

import requests
from requests.auth import HTTPBasicAuth
import json
from bs4 import BeautifulSoup

def get_content_page(base_url, page_id, user, api_key):
        
    url = f'{base_url}/wiki/api/v2/pages/{page_id}'
    
    auth = HTTPBasicAuth(user, api_key)

    headers = {
        "Accept": "application/json",
        "Content-Type": "application/json"
    }

    response = requests.request(
        "GET",
        url,
        headers=headers,
        auth=auth,
        params={"body-format": "storage"}
    )
    # レスポンスのステータスコードを確認
    if response.status_code == 200:
        # JSON形式のレスポンスを取得し、記事の内容を抽出
        json_data = response.json()
        if ('body' in json_data) and (len(json_data['body']) > 0):
            return json_data['body']['storage']['value']
        else:
            raise Exception(f'記事が見つかりませんでした: {page_id}')

    else:
        raise Exception(f'記事の取得中にエラーが発生しました: {response.status_code}')

if __name__ == "__main__":
    # confluenceの接続情報
    base_url = "https://mydomain.atlassian.net"
    page_id = 9999999999
    user = "myname@email.com"
    api_key = "API_KEY"

    # 記事の内容を取得
    content = get_content_page(base_url, page_id, user, api_key)
    
    # htmlフォーマットにかける
    soup = BeautifulSoup(content, "html.parser")

    # ファイルに出力
    with open(f"{page_id}.html", "w") as f:
        f.write(soup.prettify())

取得したページ内容はhtmlがstringで入っているので、beautifulsoupを使ってパースしてあげます。
パラメータで指定している”body-format”は3種類あるのですが、普通に使う分には”storage”で大丈夫です。
出力されたファイルを確認すると次のようになっています。

無事にhtml形式で記事内容を取得することができました。
ちなみに、生のresponse.textを確認してみると、

Unicodeで書かれていました。
コンフルの内部的にはUnicodeで扱われてるんですね。
(これ、他のAPIを叩く時に地味に大事だったりします。)

記事の更新

記事を適当に編集して、その内容をAPIを介して公開してみます。
先ほどと同様にスクリプトを書いてみましょう。
使う口はUpdate pageです。

import requests
from requests.auth import HTTPBasicAuth
import json
from bs4 import BeautifulSoup

def post_page(base_url, page_id, user, api_key, body):
    url = f"{base_url}/wiki/api/v2/pages/{page_id}"

    auth = HTTPBasicAuth(user, api_key)

    headers = {
        "Accept": "application/json",
        "Content-Type": "application/json"
    }

    payload = json.dumps( {
    "id": page_id,
    "status": "current",
    "title": "ソシテミンナノ",
    "body": {
        "representation": "storage",
        "value": body
    },
    "version": {
        "number": 2,
        "message": "いい曲ですね"
    }
    } )

    response = requests.request(
        "PUT",
        url,
        data=payload,
        headers=headers,
        auth=auth
    )
    # レスポンスのステータスコードを確認
    if response.status_code == 200:
        # JSON形式のレスポンスを取得し、記事の内容を抽出
        json_data = response.json()
        return json_data
    else:
        raise Exception(f'記事の取得中にエラーが発生しました: {response.status_code}')

if __name__ == "__main__":
    # confluenceの接続情報
    base_url = "https://mydomain.atlassian.net"
    page_id = 9999999999
    user = "myname@email.com"
    api_key = "API_KEY"

    # ファイル読み込み
    with open(f'{page_id}.html') as f:
        body = f.read()
        content = post_page(base_url, page_id, user, api_key, body)
        print (content)
    

記事の更新をするのでPUTリクエストを使います。
記事の内容はbody.valueに地のhtmlテキストをstring形式で突っ込みます。

こちらのスクリプトを実行すると、無事にコンフルの内容が更新されていました。
履歴にも載っています。

この記事の更新の方の注意点としては、バージョン番号が連番でないとダメ(その時点のcurrentの番号がnだったらn+1を指定しないといけない)だというところです。

ともあれ、これでもうコンフルを開くことなく記事の取得も更新もできるようになってハッピーですね。
リクエストパラメータの各項目の説明とかも書きたんですけどここで力尽きてしまったので、今度余裕がある時に書こうと思います。

おわりに

APIを使ってコンフルをいじれると何がいいかと言いますと、例えば特定の文字列を別の文字列に置き換えたり、内容をChatGPTに読ませて要約文を追加したりと、色々便利なことができるんじゃないのかなと思います。
やってることはただ単にAPI叩いてるだけなのですが、v2を使ってるドキュメントが検索してもあんまり出てこなかったので書いてみました。
以上です。

タイトルとURLをコピーしました