Does anyone know of any options for " bulk-uploading" .csv (MS Excel) files to a Confluence page? I have a pile of manually written knowledge incidents at hand that need to be registered as a Knowledge base on Confluence.
I have created below a pair of form (.csv) and an uploading script from a local PC via API. However, I have not tested yet. Can anyone review it and give me advice?
import pandas as pd
import requests
from requests.auth import HTTPBasicAuth
from dotenv import load_dotenv
import os
import html
import csv
Load environment variables
load_dotenv()
CONFLUENCE_EMAIL = os.getenv(“CONFLUENCE_EMAIL”)
CONFLUENCE_API_TOKEN = os.getenv(“CONFLUENCE_API_TOKEN”)
CONFLUENCE_URL = os.getenv(“CONFLUENCE_URL”)
auth = HTTPBasicAuth(CONFLUENCE_EMAIL, CONFLUENCE_API_TOKEN)
headers = {“Content-Type”: “application/json”}
Load CSV input
df = pd.read_csv(“confluence_plaintext_input_en.csv”, encoding=“utf-8”)
Convert plain text to HTML
def convert_to_html(row):
html_parts =
if pd.notna(row[‘Heading1’]) and row[‘Heading1’].strip():
html_parts.append(f"
{html.escape(row[‘Heading1’])}
“)if pd.notna(row[‘Body1’]) and row[‘Body1’].strip():
html_parts.append(f”
{html.escape(row[‘Body1’])}
“)if pd.notna(row[‘Heading2’]) and row[‘Heading2’].strip():
html_parts.append(f”
{html.escape(row[‘Heading2’])}
“)if pd.notna(row[‘Body2’]) and row[‘Body2’].strip():
html_parts.append(f”
{html.escape(row[‘Body2’])}
")return “\n”.join(html_parts)
Track log entries
log_entries =
Process and post each row
for index, row in df.iterrows():
html_body = convert_to_html(row)
page_data = {
"type": "page",
"title": row['Title'],
"space": {"key": row['SpaceKey']},
"body": {
"storage": {
"value": html_body,
"representation": "storage"
}
}
}
if pd.notna(row['ParentPageID']):
page_data["ancestors"] = [{"id": int(row['ParentPageID'])}]
response = requests.post(
f"{CONFLUENCE_URL}/rest/api/content",
headers=headers,
auth=auth,
json=page_data
)
status = response.status_code
page_id = ""
url = ""
if status in [200, 201]:
try:
page_id = response.json().get("id")
url = f"{CONFLUENCE_URL}/pages/{page_id}"
except Exception:
url = "Unknown (parse failed)"
log_entries.append({
"Title": row['Title'],
"Status": status,
"URL": url
})
print(f"[{row['Title']}] Status: {status}")
if status not in [200, 201]:
print("Error details:", response.text)
Write log to CSV
with open(“upload_log_en.csv”, mode=“w”, newline=“”, encoding=“utf-8-sig”) as logfile:
fieldnames = [“Title”, “Status”, “URL”]
writer = csv.DictWriter(logfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(log_entries)
print(“\n[INFO] Upload log saved to upload_log_en.csv”)