网站重发后PDF内嵌QR码无法识别,求Python代码修复方案
问题描述
我们完成了网站重发,现有数百份带印刷QR码的多语言PDF文件。重发后发现部分QR码指向的URL不正确,为了减少人工工作量,我写了Python代码,打算批量下载PDF、扫描识别QR码、提取URL并检测状态码,最终生成包含文档与链接的表格。但代码无法识别QR码,求帮忙修复。
附上当前代码:
import os import requests import fitz # PyMuPDF import cv2 from pyzbar.pyzbar import decode import numpy as np import csv import pdfplumber # 下载PDF的函数 def download_pdf(url, save_path): if os.path.exists(save_path): print(f"{save_path} already exists, skipping download.") return True response = requests.get(url) if response.status_code == 200: with open(save_path, 'wb') as f: f.write(response.content) print(f"Downloaded {url}") return True else: print(f"Failed to download {url}, status code: {response.status_code}") return False # 将PDF页面转为图像的函数(使用PyMuPDF) def pdf_to_images(pdf_path): doc = fitz.open(pdf_path) images = [] for page in doc: pix = page.get_pixmap() if pix.alpha: img = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, 4) else: img = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, 3) images.append(img) return images # 从图像中提取QR码的函数 def extract_qr_codes(image): qr_codes = decode(image) return [qr.data.decode('utf-8') for qr in qr_codes] # 检查URL状态码的函数 def check_url(url): try: response = requests.head(url, allow_redirects=True) return response.status_code except requests.RequestException as e: print(f"Error checking URL {url}: {e}") return 'Error' # 使用pdfplumber提取图像并解码QR码的备用方法 def extract_images_and_decode_qr(pdf_path): with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: im_list = page.images for im in im_list: bbox = (im['x0'], im['top'], im['x1'], im['bottom']) cropped_image = page.crop(bbox).to_image(resolution=300) image = np.array(cropped_image.original) image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) qr_codes = decode(image) for qr in qr_codes: print("Gefundener QR-Code:", qr.data.decode()) # 处理PDF的主函数 def process_pdfs(url_list): results = [] for url in url_list: pdf_filename = os.path.basename(url) pdf_path = os.path.join('downloads', pdf_filename) if not os.path.exists('downloads'): os.makedirs('downloads') if download_pdf(url, pdf_path): print(f"Processing {pdf_path}...") images = pdf_to_images(pdf_path) for img in images: qr_urls = extract_qr_codes(img) for qr_url in qr_urls: status_code = check_url(qr_url) results.append((pdf_filename, qr_url, status_code)) # 当未找到QR码时,尝试pdfplumber方法 if not any(result[1] for result in results if result[0] == pdf_filename): extract_images_and_decode_qr(pdf_path) if results: with open('results.csv', 'w', newline='') as file: writer = csv.writer(file) writer.writerow(['PDF Name', 'QR Code', 'Target URL', 'Status Code']) for result in results: writer.writerow(result) else: print("No results to write to CSV.") # 测试调用 if __name__ == "__main__": url_list = [ "https:.....pdf" ] process_pdfs(url_list)
修复方案
以下是针对QR码无法识别问题的具体修复步骤:
1. 优化图像预处理逻辑
pyzbar对图像格式和清晰度敏感,修改extract_qr_codes函数,增加格式转换和对比度优化:
def extract_qr_codes(image): # 处理多通道图像,转成灰度图 if len(image.shape) == 3: if image.shape[2] == 4: # RGBA转RGB再转灰度 image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB) image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # 增强图像对比度,提升印刷QR码的识别率 image = cv2.equalizeHist(image) qr_codes = decode(image) return [qr.data.decode('utf-8') for qr in qr_codes]
2. 提高PDF转图像的分辨率
默认分辨率下生成的图像可能模糊,修改pdf_to_images函数,提高dpi:
def pdf_to_images(pdf_path): doc = fitz.open(pdf_path) images = [] for page in doc: # 设置dpi为300,匹配印刷品的清晰度 pix = page.get_pixmap(dpi=300) if pix.alpha: img = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, 4) else: img = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, 3) images.append(img) return images
3. 修复pdfplumber分支的结果收集逻辑
原代码中pdfplumber识别到QR码后仅打印,未写入CSV。修改extract_images_and_decode_qr函数让它返回结果,并在主函数中收集:
def extract_images_and_decode_qr(pdf_path): qr_results = [] with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: im_list = page.images for im in im_list: bbox = (im['x0'], im['top'], im['x1'], im['bottom']) cropped_image = page.crop(bbox).to_image(resolution=300) image = np.array(cropped_image.original) image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 同样增加对比度优化 image = cv2.equalizeHist(image) qr_codes = decode(image) for qr in qr_codes: qr_url = qr.data.decode('utf-8') print("Gefundener QR-Code:", qr_url) qr_results.append(qr_url) return qr_results
同时修改主函数中的调用部分:
# 替换原pdfplumber调用代码 if not any(result[1] for result in results if result[0] == pdf_filename): print(f"Using pdfplumber to scan {pdf_path}...") qr_urls = extract_images_and_decode_qr(pdf_path) for qr_url in qr_urls: status_code = check_url(qr_url) results.append((pdf_filename, qr_url, status_code))
4. 修正CSV表头与数据的匹配问题
原表头有4列,但数据仅3列,修改表头为对应格式:
writer.writerow(['PDF Name', 'QR Code URL', 'Status Code'])
内容的提问来源于stack exchange,提问作者PeterPan1888
相关产品推荐
相关产品推荐

