# SPDX-FileCopyrightText: 2025 James R. Barlow # SPDX-License-Identifier: MIT """Compare two PDFs.""" from __future__ import annotations from io import BytesIO from pathlib import Path from tempfile import TemporaryDirectory import pikepdf import pymupdf import streamlit as st from lxml import etree from streamlit_pdf_viewer import pdf_viewer def do_metadata(pdf): with pikepdf.open(pdf) as pdf: with pdf.open_metadata() as meta: xml_txt = str(meta) parser = etree.XMLParser(remove_blank_text=True) tree = etree.fromstring(xml_txt, parser=parser) st.code( etree.tostring(tree, pretty_print=True).decode("utf-8"), language="xml", ) st.write(pdf.docinfo) st.write("Number of pages:", len(pdf.pages)) def main(): st.set_page_config(layout="wide") st.title("PDF Compare") st.write("Compare two PDFs.") col1, col2 = st.columns(2) with col1: uploaded_pdf1 = st.file_uploader("Upload a PDF", type=["pdf"], key='pdf1') with col2: uploaded_pdf2 = st.file_uploader("Upload a PDF", type=["pdf"], key='pdf2') if uploaded_pdf1 is None or uploaded_pdf2 is None: return pdf_bytes1 = uploaded_pdf1.getvalue() pdf_bytes2 = uploaded_pdf2.getvalue() with st.expander("PDF Metadata"): col1, col2 = st.columns(2) with col1: do_metadata(BytesIO(pdf_bytes1)) with col2: do_metadata(BytesIO(pdf_bytes2)) with TemporaryDirectory() as d: Path(d, "1.pdf").write_bytes(pdf_bytes1) Path(d, "2.pdf").write_bytes(pdf_bytes2) with st.expander("Text"): doc1 = pymupdf.open(Path(d, "1.pdf")) doc2 = pymupdf.open(Path(d, "2.pdf")) for i, page1_2 in enumerate(zip(doc1, doc2, strict=False)): st.write(f"Page {i + 1}") page1, page2 = page1_2 col1, col2 = st.columns(2) with col1, st.container(border=True): st.write(page1.get_text()) with col2, st.container(border=True): st.write(page2.get_text()) with st.expander("PDF Viewer"): col1, col2 = st.columns(2) with col1: pdf_viewer(Path(d, "1.pdf"), key='pdf_viewer1', render_text=True) with col2: pdf_viewer(Path(d, "2.pdf"), key='pdf_viewer2', render_text=True) if __name__ == "__main__": main()