Communitygithub.com

kyopark2014/strands-skills

Strands SDK上でエージェントスキルを使用する方法を示します。

strands-skills とは?

このスキルは、Strands SDKを使用するAIエージェント向けに設計された、PDF処理に関する包括的なガイドを提供します。主にPythonライブラリ(reportlab、pypdf、pdfplumber)を活用し、エージェントがコードを実行してPDFの作成、読み取り、結合、分割、回転、パスワード保護、テーブル抽出などの操作を自動化できるようにします。特に、韓国語を含むPDFを作成するためのフォント登録手順が詳細に説明されており、macOS環境での注意点や代替フォントの優先順位も明確に示されています。このスキルはClaude Code、Cursor、Codexなどのコード実行をサポートするプラットフォームで利用でき、出力ファイルはすべて`artifacts/`ディレクトリに保存されます。

対応~Claude Code~Codex CLI~Cursor
npx skills add kyopark2014/strands-skills

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

PDF処理ガイド

概要

このガイドでは、Pythonライブラリを使用した基本的なPDF処理操作について説明します。 execute_codeツールを使用して、以下に示すPythonコードを実行してください。 生成されたファイルはすべてartifacts/ディレクトリに保存する必要があります。

韓国語フォント設定(必須 — すべてのPDF生成コードに含めること)

韓国語を含むPDFを作成する場合は、必ず韓国語フォントを登録する必要があります。 以下のフォント登録コードをすべてのPDF生成コードの先頭に必ず含めてください。

重要: macOSのAppleSDGothicNeo.ttcはPostScriptアウトラインであるため、reportlabで使用できません。

フォント優先順位:

  1. assets/NanumGothic-Regular.ttf(TTFファイル — 最も確実)
  2. CIDフォント HYGothic-Medium(reportlab内蔵 — 別途ファイル不要、確実なフォールバック)
import os
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase.cidfonts import UnicodeCIDFont

def register_korean_font():
    """韓国語フォントを登録し、フォント名を返す。PDF生成前に必ず呼び出すこと。"""
    # 第1優先: NanumGothic TTF
    ttf_paths = [
        os.path.join("assets", "NanumGothic-Regular.ttf"),
        "/usr/share/fonts/truetype/nanum/NanumGothic.ttf",
        "/usr/share/fonts/nanum/NanumGothic.ttf",
        "/Library/Fonts/NanumGothic.ttf",
    ]
    for path in ttf_paths:
        if os.path.exists(path):
            try:
                pdfmetrics.registerFont(TTFont("KoreanFont", path))
                return "KoreanFont"
            except Exception:
                continue

    # 第2優先: CIDフォント(reportlab内蔵、別途ファイル不要)
    try:
        pdfmetrics.registerFont(UnicodeCIDFont("HYGothic-Medium"))
        return "HYGothic-Medium"
    except Exception:
        pass

    return "Helvetica"  # 最終フォールバック(韓国語非対応)

font_name = register_korean_font()

新しいPDFの作成 (reportlab)

基本的なPDF作成(英語のみ)

from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
import os

os.makedirs("artifacts", exist_ok=True)
c = canvas.Canvas("artifacts/hello.pdf", pagesize=A4)
width, height = A4
c.drawString(100, height - 100, "Hello World!")
c.save()

韓国語PDF作成(推奨パターン)

import os
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase.cidfonts import UnicodeCIDFont

# 1) 韓国語フォント登録
font_name = "Helvetica"
for path in [os.path.join("assets", "NanumGothic-Regular.ttf"),
             "/usr/share/fonts/truetype/nanum/NanumGothic.ttf"]:
    if os.path.exists(path):
        try:
            pdfmetrics.registerFont(TTFont("KoreanFont", path))
            font_name = "KoreanFont"
            break
        except Exception:
            continue
if font_name == "Helvetica":
    try:
        pdfmetrics.registerFont(UnicodeCIDFont("HYGothic-Medium"))
        font_name = "HYGothic-Medium"
    except Exception:
        pass

# 2) 韓国語スタイル定義
styles = getSampleStyleSheet()
styles.add(ParagraphStyle("Title_KO",   parent=styles["Title"],    fontName=font_name, fontSize=20, spaceAfter=20, textColor=colors.HexColor("#1a1a2e")))
styles.add(ParagraphStyle("H1_KO",      parent=styles["Heading1"], fontName=font_name, fontSize=16, spaceAfter=14, textColor=colors.HexColor("#16213e")))
styles.add(ParagraphStyle("H2_KO",      parent=styles["Heading2"], fontName=font_name, fontSize=14, spaceAfter=12, textColor=colors.HexColor("#0f3460")))
styles.add(ParagraphStyle("Normal_KO",  parent=styles["Normal"],   fontName=font_name, fontSize=10, leading=14, spaceAfter=8))
styles.add(ParagraphStyle("Bullet_KO",  parent=styles["Normal"],   fontName=font_name, fontSize=10, leading=14, leftIndent=20, bulletIndent=10))

# 3) PDFビルド
os.makedirs("artifacts", exist_ok=True)
doc = SimpleDocTemplate("artifacts/report.pdf", pagesize=A4,
    topMargin=0.8*inch, bottomMargin=0.8*inch, leftMargin=0.75*inch, rightMargin=0.75*inch)

story = []
story.append(Paragraph("レポートタイトル", styles["Title_KO"]))
story.append(Spacer(1, 16))
story.append(Paragraph("1. 概要", styles["H1_KO"]))
story.append(Paragraph("このレポートはサンプル内容を含んでいます。", styles["Normal_KO"]))
story.append(Spacer(1, 8))
story.append(Paragraph("2. 詳細内容", styles["H1_KO"]))
story.append(Paragraph("• 最初の項目", styles["Bullet_KO"]))
story.append(Paragraph("• 2番目の項目", styles["Bullet_KO"]))
story.append(PageBreak())
story.append(Paragraph("3. 付録", styles["H1_KO"]))
story.append(Paragraph("追加内容です。", styles["Normal_KO"]))

doc.build(story)
print("PDF作成完了: artifacts/report.pdf")

韓国語テーブルを含むPDF

import os
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase.cidfonts import UnicodeCIDFont

# フォント登録
font_name = "Helvetica"
for path in [os.path.join("assets", "NanumGothic-Regular.ttf"),
             "/usr/share/fonts/truetype/nanum/NanumGothic.ttf"]:
    if os.path.exists(path):
        try:
            pdfmetrics.registerFont(TTFont("KoreanFont", path))
            font_name = "KoreanFont"
            break
        except Exception:
            continue
if font_name == "Helvetica":
    try:
        pdfmetrics.registerFont(UnicodeCIDFont("HYGothic-Medium"))
        font_name = "HYGothic-Medium"
    except Exception:
        pass

styles = getSampleStyleSheet()
styles.add(ParagraphStyle("Title_KO",  parent=styles["Title"],  fontName=font_name, fontSize=18, textColor=colors.HexColor("#1a1a2e")))
styles.add(ParagraphStyle("Normal_KO", parent=styles["Normal"], fontName=font_name, fontSize=10))

os.makedirs("artifacts", exist_ok=True)
doc = SimpleDocTemplate("artifacts/table_report.pdf", pagesize=A4)

data = [
    ["項目", "説明", "コスト"],
    ["サーバー", "EC2インスタンス", "$120"],
    ["ストレージ", "S3バケット", "$45"],
    ["データベース", "RDS PostgreSQL", "$89"],
]
table = Table(data, colWidths=[120, 200, 80])
table.setStyle(TableStyle([
    ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#e8eaf6")),
    ("TEXTCOLOR", (0, 0), (-1, 0), colors.HexColor("#1a1a2e")),
    ("FONTNAME", (0, 0), (-1, -1), font_name),
    ("FONTSIZE", (0, 0), (-1, -1), 10),
    ("GRID", (0, 0), (-1, -1), 0.5, colors.HexColor("#bdbdbd")),
    ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
    ("TOPPADDING", (0, 0), (-1, -1), 6),
    ("BOTTOMPADDING", (0, 0), (-1, -1), 6),
]))

doc.build([
    Paragraph("コスト分析レポート", styles["Title_KO"]),
    Spacer(1, 16),
    table
])
print("PDF作成完了: artifacts/table_report.pdf")

reportlabに関する重要な注意事項

  • 韓国語テキストを使用するときは、必ず上記のフォント登録コードを含めてください。
  • macOSのAppleSDGothicNeo.ttcはPostScriptアウトラインであるため、reportlabで使用できません。絶対に使用しないでください。
  • TTFフォント(assets/NanumGothic-Regular.ttf)がない場合は、CIDフォントHYGothic-Mediumを使用してください。
  • フォントを登録しないと、韓国語が文字化けしたり、四角(□)で表示されたりします。
  • ReportLab PDFではUnicodeの下付き/上付き文字(₀₁₂₃₄₅₆₇₈₉)を絶対に使用しないでください。代わりに<sub>タグと<sup>タグを使用してください。

PDFの読み取り (pypdf)

テキスト抽出

from pypdf import PdfReader

reader = PdfReader("input.pdf")
text = ""
for page in reader.pages:
    text += page.extract_text()
print(text)

PDFの結合

from pypdf import PdfWriter, PdfReader

writer = PdfWriter()
for pdf_file in ["doc1.pdf", "doc2.pdf"]:
    reader = PdfReader(pdf_file)
    for page in reader.pages:
        writer.add_page(page)

with open("artifacts/merged.pdf", "wb") as output:
    writer.write(output)

PDFの分割

from pypdf import PdfReader, PdfWriter

reader = PdfReader("input.pdf")
for i, page in enumerate(reader.pages):
    writer = PdfWriter()
    writer.add_page(page)
    with open(f"artifacts/page_{i+1}.pdf", "wb") as output:
        writer.write(output)

ページの回転

from pypdf import PdfReader, PdfWriter

reader = PdfReader("input.pdf")
writer = PdfWriter()
page = reader.pages[0]
page.rotate(90)
writer.add_page(page)

with open("artifacts/rotated.pdf", "wb") as output:
    writer.write(output)

パスワード保護

from pypdf import PdfReader, PdfWriter

reader = PdfReader("input.pdf")
writer = PdfWriter()
for page in reader.pages:
    writer.add_page(page)
writer.encrypt("userpassword", "ownerpassword")

with open("artifacts/encrypted.pdf", "wb") as output:
    writer.write(output)

テーブル抽出 (pdfplumber)

import pdfplumber

with pdfplumber.open("input.pdf") as pdf:
    for page in pdf.pages:
        text = page.extract_text()
        tables = page.extract_tables()
        for table in tables:
            for row in table:
                print(row)

クイックリファレンス

タスクライブラリ主要関数
PDF作成reportlabSimpleDocTemplate / canvas
読み取り/結合/分割pypdfPdfReader / PdfWriter
テーブル抽出pdfplumberpage.extract_tables()
パスワード保護pypdfwriter.encrypt()
ページ回転pypdfpage.rotate()

関連スキル