add_signature.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import io
  2. import logging
  3. import os
  4. import sys
  5. import pdfplumber
  6. import requests
  7. from PIL import Image
  8. from PyPDF2 import PdfReader, PdfWriter
  9. from reportlab.lib.pagesizes import A4
  10. from reportlab.pdfgen import canvas
  11. # 配置日志
  12. logging.basicConfig(level=logging.INFO)
  13. logger = logging.getLogger(__name__)
  14. def find_signature_positions(pdf_path, target_texts=["签字或盖章", "技术支持单位(盖章)"]):
  15. """查找所有签名位置"""
  16. positions = []
  17. with pdfplumber.open(pdf_path) as pdf:
  18. for i, page in enumerate(pdf.pages):
  19. for word in page.extract_words():
  20. for target in target_texts:
  21. if target in word["text"]:
  22. x, y = word["x0"], word["top"]
  23. positions.append((i, int(x), int(y), target))
  24. logger.info(f"找到签名位置: 第{i}页, {target} at ({x}, {y})")
  25. # 返回结果:所有"签字或盖章"和"技术支持单位(盖章)"的位置
  26. if len(positions) == 0 or positions == []:
  27. return None
  28. # 返回结果:第二个"签字或盖章"和技术支持单位位置
  29. result = []
  30. if len(positions) >= 2:
  31. result.append(positions[1])
  32. # 第二个出现的位置(索引1)
  33. else:
  34. result.append(positions[0])
  35. return result
  36. def add_signature_to_pdf(input_pdf, output_pdf, signature_img, positions, offset_x=30, offset_y=-10):
  37. """添加签名到PDF"""
  38. reader = PdfReader(input_pdf)
  39. writer = PdfWriter()
  40. a4_width, a4_height = A4 # (595.2, 841.68)
  41. for page_index in range(len(reader.pages)):
  42. page = reader.pages[page_index]
  43. for pos in positions:
  44. if pos[0] == page_index:
  45. packet = io.BytesIO()
  46. can = canvas.Canvas(packet, pagesize=A4)
  47. img = Image.open(signature_img)
  48. img_width, img_height = img.size
  49. aspect_ratio = img_height / img_width
  50. new_width = 43 * (72 / 25.4) # 40mm ≈ 113.39点
  51. new_height = new_width * aspect_ratio
  52. x, y = pos[1], a4_height - pos[2]
  53. if pos[3] == "技术支持单位(盖章)":
  54. y = y - new_height / 2
  55. else:
  56. y = y - new_height / 3 * 2
  57. x = max(0, min(x, a4_width - new_width))
  58. y = max(0, min(y, a4_height - new_height))
  59. can.drawImage(signature_img, x, y, width=new_width, height=new_height, mask='auto')
  60. can.save()
  61. packet.seek(0)
  62. overlay_pdf = PdfReader(packet)
  63. page.merge_page(overlay_pdf.pages[0])
  64. writer.add_page(page)
  65. with open(output_pdf, "wb") as f:
  66. writer.write(f)
  67. def download_file(url, local_filename):
  68. """下载文件到临时目录"""
  69. with requests.get(url, stream=True) as r:
  70. r.raise_for_status()
  71. with open(local_filename, 'wb') as f:
  72. for chunk in r.iter_content(chunk_size=8192):
  73. f.write(chunk)
  74. return local_filename
  75. def add_signature(url, pdfFilename, signature_img, signature_pdf):
  76. """把水印添加到pdf中"""
  77. # 下载PDF文件
  78. local_pdf = download_file(url, pdfFilename)
  79. # 查找签名位置(使用默认公章图片)
  80. positions = find_signature_positions(local_pdf)
  81. if len(positions) == 0:
  82. os.remove(local_pdf)
  83. return
  84. # 生成带公章的PDF
  85. add_signature_to_pdf(local_pdf, signature_pdf, signature_img, positions)
  86. if __name__ == '__main__':
  87. if len(sys.argv) < 3:
  88. print("Usage: add_watermark.py <url> <pdf_file_in> <signature_img> <signature_pdf>")
  89. sys.exit(1)
  90. pdf_file_url = sys.argv[1]
  91. pdfFilename = sys.argv[2] # 要加水印的文件名
  92. signature_img = sys.argv[3] # 要加水印的文件名
  93. signature_pdf = sys.argv[4] # 加好水印的结果文件
  94. # name = str(uuid.uuid4()) + ".pdf"
  95. # pdf_file_url = "https://bzdcoldverifyoss.baozhida.cn/UpImage/1754036272edee05b2-6032-430c-a39b-c83490764dd9.pdf"
  96. # pdfFilename = "/Users/zoie/work/bzd_project/ColdVerify_server/ofile/" + name
  97. # signature_img = "/Users/zoie/work/bzd_project/ColdVerify_server/script/报告专用章.png"
  98. # signature_pdf = "/Users/zoie/work/bzd_project/ColdVerify_server/ofile/signature" + name
  99. add_signature(pdf_file_url, pdfFilename, signature_img, signature_pdf)
  100. print(signature_pdf)