0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PDFを解析して画像も含めてAzure Blobにアップする

0
Posted at

1. 基本設計

概要

Azure App Serviceを使用して、PDFドキュメントをアップロードし、解析してMarkdown形式に変換するアプリケーションを開発します。PDF内の図は画像として保存し、Markdownには画像のリンクを記載します。保存先はAzure Blob Storageを使用し、Markdownドキュメントはアプリの画面で表示します。

要件

  • PDFドキュメントのアップロード機能
  • PDFドキュメントの解析とMarkdown形式への変換
  • PDF内の図を画像として保存し、Markdownにリンクを記載
  • 画像とMarkdownの保存先としてAzure Blob Storageを使用
  • Markdownドキュメントの表示機能
  • 開発言語はPython
  • フレームワークとしてstreamlitを使用

2. システム構成図

3. システムフロー図

4. 必要なパッケージ、ツール

  • Streamlit: Webアプリケーションフレームワーク
  • azure-storage-blob: Azure Blob Storageとの連携
  • PyMuPDF: PDF解析ライブラリ
  • Pillow: 画像処理ライブラリ
  • markdown2: Markdown変換ライブラリ

5. 詳細設計

PDFアップロード機能

  • エンドポイント: /upload
  • メソッド: POST
  • 処理内容: PDFファイルを受け取り、Azure Blob Storageに保存
pip install streamlit azure-storage-blob PyMuPDF Pillow markdown2
import streamlit as st
from azure.storage.blob import BlobServiceClient

# Azure Blob Storageの設定
blob_service_client = BlobServiceClient.from_connection_string("your_connection_string")
container_name = "pdf-container"

def upload_pdf(file):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=file.name)
    blob_client.upload_blob(file)
    st.success("PDF uploaded successfully!")

st.title("PDF Uploader")
uploaded_file = st.file_uploader("Choose a PDF file", type="pdf")
if uploaded_file is not None:
    upload_pdf(uploaded_file)

PDF解析とMarkdown変換機能

  • エンドポイント: 内部処理
  • 処理内容:
    1. Azure Blob StorageからPDFを取得
    2. PyMuPDFを使用してPDFを解析
    3. 画像を抽出し、PillowでJPEG形式に変換
    4. 画像をAzure Blob Storageに保存
    5. テキストをMarkdown形式に変換し、画像リンクを挿入
    6. MarkdownファイルをAzure Blob Storageに保存
import fitz  # PyMuPDF
from PIL import Image
import io

def list_blobs(container_name):
    container_client = blob_service_client.get_container_client(container_name)
    blob_list = container_client.list_blobs()
    return [blob.name for blob in blob_list]

def parse_pdf(file_path):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=file_path)
    pdf_bytes = blob_client.download_blob().readall()
    doc = fitz.open(stream=pdf_bytes, filetype="pdf")
    markdown_text = ""
    for page_num in range(len(doc)):
        page = doc.load_page(page_num)
        text = page.get_text("text")
        markdown_text += text + "\n\n"
        images = page.get_images(full=True)
        for img_index, img in enumerate(images):
            xref = img[0]   # (4, 0, 326, 8, 8, 'DeviceRGB', '', 'Image1', 'DCTDecode', 0)
            smask = img[1]
            ext_type = img[8] # FlateDecode is png, DCTDecode is jpeg
            base_image = doc.extract_image(xref)
            image_bytes = base_image["image"]
            image = Image.open(io.BytesIO(image_bytes))
            image_path = f"image_{page_num}_{img_index}.jpeg"
            image.save(image_path)
            upload_image_to_blob(image_path)
            markdown_text += f"!Image\n\n"
    return markdown_text

def upload_image_to_blob(image_path):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=image_path)
    with open(image_path, "rb") as data:
        blob_client.upload_blob(data)

def convert_to_markdown(file_path):
    markdown_text = parse_pdf(file_path)
    markdown_file_path = file_path.replace(".pdf", ".md")
    with open(markdown_file_path, "w") as md_file:
        md_file.write(markdown_text)
    upload_markdown_to_blob(markdown_file_path)

def upload_markdown_to_blob(markdown_file_path):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=markdown_file_path)
    with open(markdown_file_path, "rb") as data:
        blob_client.upload_blob(data)

Markdown表示機能

  • エンドポイント: /display
  • メソッド: GET
  • 処理内容: Azure Blob StorageからMarkdownファイルを取得し、画面に表示
def display_markdown(file_path):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=file_path)
    markdown_content = blob_client.download_blob().readall().decode("utf-8")
    st.markdown(markdown_content)

st.title("Markdown Viewer")
markdown_file = st.text_input("Enter the name of the markdown file to display")
if markdown_file:
    display_markdown(markdown_file)

Streamlitアプリケーション統合

このコードでは、以下の機能を実装しています:

  1. PDFファイルのアップロード
  2. Blob Storageに保存されているPDFファイルのリスト表示と選択
  3. 選択したPDFファイルのMarkdown形式への変換
  4. Blob Storageに保存されているMarkdownファイルのリスト表示と選択
  5. 選択したMarkdownファイルの表示
import streamlit as st
from azure.storage.blob import BlobServiceClient
import fitz  # PyMuPDF
from PIL import Image
import io

# Azure Blob Storageの設定
blob_service_client = BlobServiceClient.from_connection_string("your_connection_string")
container_name = "pdf-container"

def list_blobs(container_name):
    container_client = blob_service_client.get_container_client(container_name)
    blob_list = container_client.list_blobs()
    return [blob.name for blob in blob_list]

def upload_pdf(file):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=file.name)
    blob_client.upload_blob(file)
    st.success("PDF uploaded successfully!")

def parse_pdf(file_path):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=file_path)
    pdf_bytes = blob_client.download_blob().readall()
    doc = fitz.open(stream=pdf_bytes, filetype="pdf")
    markdown_text = ""
    for page_num in range(len(doc)):
        page = doc.load_page(page_num)
        text = page.get_text("text")
        markdown_text += text + "\n\n"
        images = page.get_images(full=True)
        for img_index, img in enumerate(images):
            xref = img[0]   # (4, 0, 326, 8, 8, 'DeviceRGB', '', 'Image1', 'DCTDecode', 0)
            smask = img[1]
            ext_type = img[8] # FlateDecode is png, DCTDecode is jpeg
            base_image = doc.extract_image(xref)
            image_bytes = base_image["image"]
            image = Image.open(io.BytesIO(image_bytes))
            image_path = f"image_{page_num}_{img_index}.jpeg"
            image.save(image_path)
            upload_image_to_blob(image_path)
            markdown_text += f"!Image\n\n"
    return markdown_text

def upload_image_to_blob(image_path):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=image_path)
    with open(image_path, "rb") as data:
        blob_client.upload_blob(data)

def convert_to_markdown(file_path):
    markdown_text = parse_pdf(file_path)
    markdown_file_path = file_path.replace(".pdf", ".md")
    with open(markdown_file_path, "w") as md_file:
        md_file.write(markdown_text)
    upload_markdown_to_blob(markdown_file_path)

def upload_markdown_to_blob(markdown_file_path):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=markdown_file_path)
    with open(markdown_file_path, "rb") as data:
        blob_client.upload_blob(data)

def display_markdown(file_path):
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=file_path)
    markdown_content = blob_client.download_blob().readall().decode("utf-8")
    st.markdown(markdown_content)

# Streamlitアプリケーション
st.title("PDF to Markdown Converter")

# PDFアップロード
st.header("Upload PDF")
uploaded_file = st.file_uploader("Choose a PDF file", type="pdf")
if uploaded_file is not None:
    upload_pdf(uploaded_file)

# PDF変換
st.header("Convert PDF to Markdown")
pdf_files = list_blobs(container_name)
selected_pdf = st.selectbox("Select a PDF file to convert", pdf_files)
if st.button("Convert to Markdown"):
    convert_to_markdown(selected_pdf)
    st.success("PDF converted to Markdown successfully!")

# Markdown表示
st.header("View Markdown Files")
markdown_files = [file for file in list_blobs(container_name) if file.endswith(".md")]
selected_markdown = st.selectbox("Select a Markdown file to view", markdown_files)
if selected_markdown:
    display_markdown(selected_markdown)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?