Python中PdfFileReader读取网络PDF失败,请求解决方案
解决内嵌在HTML中的PDF读取问题
嘿,我来帮你搞定这个PDF读取的麻烦!你遇到的问题根源很明确:第一个URL是直接返回PDF二进制文件流,所以PdfFileReader可以直接处理;但第二个URL返回的是包含PDF数据的HTML页面(也就是你说的"application data"形式),直接把这个URL传给PdfFileReader,它读到的是HTML代码而非真实的PDF内容,自然会报错。
下面分两种常见场景给你对应的代码修改方案:
场景1:PDF以Data URI形式内嵌在HTML标签中(比如iframe/embed)
大多数这类网站会把PDF编码成base64格式,放在iframe或embed标签的src属性里(格式类似data:application/pdf;base64,JVBERi0xLjQK...)。我们需要先解析HTML提取出这段base64数据,解码后再传给PdfFileReader。
示例代码:
import requests from bs4 import BeautifulSoup import PyPDF2 import base64 import io # 替换成你的第二个URL target_url = "https://example.com/your-page-with-embedded-pdf" # 1. 获取HTML页面内容 response = requests.get(target_url) response.raise_for_status() # 确保请求成功,失败则抛出异常 # 2. 解析HTML,找到内嵌PDF的标签 soup = BeautifulSoup(response.text, "html.parser") # 优先找iframe标签,也可以根据实际情况换成embed标签 pdf_element = soup.find("iframe", {"type": "application/pdf"}) or soup.find("embed", {"type": "application/pdf"}) if pdf_element: # 提取Data URI并拆分出base64部分 pdf_data_uri = pdf_element["src"] try: _, base64_content = pdf_data_uri.split("base64,", 1) except ValueError: print("该PDF不是以base64编码的Data URI形式存在") exit() # 3. 解码base64为二进制PDF数据 pdf_bytes = base64.b64decode(base64_content) # 4. 将二进制数据转为类文件对象,供PdfFileReader读取 pdf_file = io.BytesIO(pdf_bytes) # 现在可以正常读取PDF了 reader = PyPDF2.PdfFileReader(pdf_file) print(f"成功读取PDF,总页数:{reader.getNumPages()}") else: print("在页面中未找到内嵌的PDF标签(iframe/embed)")
场景2:PDF是通过JavaScript动态加载的
如果网站的PDF是通过AJAX或者其他JS逻辑动态渲染到页面中的,用requests+BeautifulSoup可能抓不到数据,这时候需要用浏览器自动化工具(比如Selenium)模拟真实浏览器加载页面,获取渲染后的内容。
示例代码:
from selenium import webdriver from selenium.webdriver.common.by import By import PyPDF2 import base64 import io # 替换成你的第二个URL target_url = "https://example.com/your-dynamic-page-with-pdf" # 初始化浏览器(这里用Chrome,需要提前安装ChromeDriver) driver = webdriver.Chrome() driver.get(target_url) driver.implicitly_wait(10) # 等待页面加载完成 # 查找内嵌PDF的iframe标签 try: pdf_iframe = driver.find_element(By.TAG_NAME, "iframe") pdf_data_uri = pdf_iframe.get_attribute("src") # 后续解码步骤和场景1一致 _, base64_content = pdf_data_uri.split("base64,", 1) pdf_bytes = base64.b64decode(base64_content) pdf_file = io.BytesIO(pdf_bytes) reader = PyPDF2.PdfFileReader(pdf_file) print(f"成功读取动态加载的PDF,总页数:{reader.getNumPages()}") except Exception as e: print(f"读取失败:{str(e)}") finally: driver.quit() # 关闭浏览器
注意事项:
- 不同网站的内嵌逻辑可能不同,你可以先打开目标页面的开发者工具(F12),查看HTML结构,确认PDF数据具体藏在哪个标签或位置,再调整代码中的查找逻辑。
- 如果遇到反爬机制,可能需要给
requests添加请求头(比如User-Agent),或者在Selenium中配置浏览器选项模拟正常用户行为。
内容的提问来源于stack exchange,提问作者Bosiwow




