import gradio as gr import fitz import csv import tempfile import os def analyze_pdf(file_obj): if file_obj is None: return "ファイルをアップロードしてください", None doc = fitz.open(file_obj.name) temp_dir = tempfile.mkdtemp() results = [] full_text_order = [] for page_num in range(len(doc)): page = doc[page_num] blocks = page.get_text("rawdict")["blocks"] char_idx = 0 for b_idx, block in enumerate(blocks): if "lines" not in block: continue for l_idx, line in enumerate(block["lines"]): for s_idx, span in line["spans"]: font = span.get("font", "") for char in span["chars"]: c = char["c"] bbox = char["bbox"] results.append({ "index": char_idx, "char": c, "x0": round(bbox[0], 2), "y0": round(bbox[1], 2), "x1": round(bbox[2], 2), "y1": round(bbox[3], 2), "block": b_idx, "line": l_idx, "span": s_idx, "font": font, }) full_text_order.append(c) char_idx += 1 doc.close() csv_path = os.path.join(temp_dir, "char_order.csv") with open(csv_path, "w", encoding="utf-8-sig", newline="") as f: writer = csv.DictWriter(f, fieldnames=["index","char","x0","y0","x1","y1","block","line","span","font"]) writer.writeheader() writer.writerows(results) # 最初の200文字を表示 preview = "".join(full_text_order[:500]) summary = f"総文字数: {len(full_text_order)}\n\n抽出順テキスト(先頭500文字):\n{preview}" return summary, csv_path with gr.Blocks(title="PDF文字順序解析") as demo: gr.Markdown("## PDF文字抽出順序の解析") gr.Markdown("PDFをアップロードすると、内部のテキスト抽出順序をCSVで出力します") with gr.Row(): file_input = gr.File(label="PDFファイル", file_types=[".pdf"], type="file") run_btn = gr.Button("解析実行", variant="primary") summary_box = gr.Textbox(label="結果サマリ", lines=15) csv_output = gr.File(label="文字順序CSV") run_btn.click(fn=analyze_pdf, inputs=[file_input], outputs=[summary_box, csv_output]) if __name__ == "__main__": demo.launch()