如何在StreamLit中使用PyPDFLoader处理上传的PDF并保留页码?
问题:Streamlit上传PDF使用PyPDFLoader报错且需保留页码信息
我基于StreamLit构建PDF文档读取Web应用,使用langchain.document_loaders.PyPDFLoader加载上传的PDF时触发如下错误:
TypeError: stat: path should be string, bytes, os.PathLike or integer, not list
错误堆栈信息:
File "/opt/homebrew/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 552, in _run_script exec(code, module.__dict__) File "/Users/shuhulhandoo/MetaGeeks/PDF-URL_QA/app.py", line 133, in <module> main() File "/Users/shuhulhandoo/MetaGeeks/PDF-URL_QA/app.py", line 75, in main loader = PyPDFLoader(pdf) ^^^^^^^^^^^^^^^^ File "/opt/homebrew/lib/python3.11/site-packages/langchain/document_loaders/pdf.py", line 92, in __init__ super().__init__(file_path) File "/opt/homebrew/lib/python3.11/site-packages/langchain/document_loaders/pdf.py", line 42, in __init__ if not os.path.isfile(self.file_path) and self._is_valid_url(self.file_path): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen genericpath>", line 30, in isfile
我的上传代码逻辑:
import streamlit as st from langchain.document_loaders import PyPDFLoader uploaded_file = st.file_uploader("Upload PDF", type="pdf") if uploader_file is not None: loader = PyPDFLoader(uploaded_file)
我需要保留页码等文档源信息,之前尝试用PyPDF2的PdfReader逐页提取文本,但会丢失页码信息,求解决办法。
解决方案
核心问题原因
PyPDFLoader仅接受文件路径字符串作为参数,但Streamlit的st.file_uploader返回的是UploadedFile类文件对象,并非本地文件路径,直接传入会触发类型错误。
方法1:临时保存上传文件再加载
将上传的UploadedFile保存到本地临时文件,再用PyPDFLoader加载该文件路径,既能满足参数要求,又能保留页码元数据:
import streamlit as st from langchain.document_loaders import PyPDFLoader import tempfile import os uploaded_file = st.file_uploader("Upload PDF", type="pdf") if uploaded_file is not None: # 创建临时PDF文件,写入上传内容 with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file: tmp_file.write(uploaded_file.getbuffer()) tmp_file_path = tmp_file.name # 加载临时文件并提取带页码的内容 loader = PyPDFLoader(tmp_file_path) document_pages = loader.load() # 验证页码信息:每个Document对象的metadata包含page_number for page in document_pages: st.subheader(f"页码: {page.metadata['page_number']}") st.write(page.page_content[:500]) # 显示每页前500字符 # 清理临时文件,避免磁盘占用 os.unlink(tmp_file_path)
方法2:使用支持类文件对象的PyPDFium2Loader(无需临时文件)
LangChain的PyPDFium2Loader支持直接传入UploadedFile对象,无需保存临时文件,需先安装依赖:
pip install pypdfium2
代码示例:
import streamlit as st from langchain.document_loaders import PyPDFium2Loader uploaded_file = st.file_uploader("Upload PDF", type="pdf") if uploaded_file is not None: loader = PyPDFium2Loader(uploaded_file) document_pages = loader.load() # 遍历并展示带页码的内容 for page in document_pages: st.subheader(f"页码: {page.metadata['page_number']}") st.write(page.page_content[:500])
两种方法生成的Document对象都会在metadata字段中包含page_number,满足保留页码信息的需求。
内容的提问来源于stack exchange,提问作者Shuhul Handoo
相关产品推荐
相关产品推荐

