本帖最后由 制冷设备 于 2021-3-2 13:28 编辑
1.说明
缘起:大佬 @我没有失眠啊i 的悬赏贴,要用py去除pdf图片水印https://www.52pojie.cn/forum.php?mod=viewthread&tid=1372040,正好之前写过类似的代码https://www.52pojie.cn/thread-1285821-1-1.html,试了下也可以,还是找水印类型,定xref位置删除去除的思路。大佬问,能删文字水印不?先搜py库和例子,还真不好找,最多的是用opencv去除图片类水印以及批量加水印的帖子,不太好搞。
但研究了下pymupdf,还是可以实现,具体如下。
2021.3.2
实际更换为pypdf2实现
2.分析
老样子,还是先分析水印,查看页面内容,是Text类,与正文文本同一类,直接用fitz读取分辨不出。
2.1 思路
单独提取一页,然后删除页面内容只剩水印,识别提取作为特征码,然后遍历pdf查找xref位置,定位删除。
2021.3.2 思路调整
pypdf2去除水印代码例子对水印识别会出错,但对pdf操作符识别操作的方法可行
更改思路识别Pdf内文字样式,进一步分析水印文字样式,将其代下改为0
2.2 调试
使用fitz库中的页面readContents()方法对单独水印页读取,得到如下代码,看操作符其实可以定位水印内容就是<>中的字符串。
2021.3.2 调试
遍历识别字体样式,获得字体样式列表,发现本例中pdf文字大小仅有1和16,可知水印字体大小为16
针对字体大小进行识别,同时将其更改为0,可执行。
执行结果,可视字体水印无,内容栏实际存在。
3. 代码实现
from PyPDF2 import PdfFileReader, PdfFileWriter
from PyPDF2.pdf import ContentStream
from PyPDF2.generic import TextStringObject, NameObject, NumberObject
from PyPDF2.utils import b_
def remove_watermark(input_file,wm_size, output_file):
with open(input_file, "rb") as f:
source = PdfFileReader(f, "rb")
output = PdfFileWriter()
for page in range(source.getNumPages()):
page = source.getPage(page)
content_object = page.getContents()
content = ContentStream(content_object, source)
for operands, operator in content.operations:
if operator == b_("Tf"):
if operands[1] == NumberObject(wm_size):
operands[1]=NumberObject(0)
page.__setitem__(NameObject('/Contents'), content)
output.addPage(page)
with open(output_file, "wb") as outputStream:
output.write(outputStream)
f.close()
def font_size(input_file):
font_size = []
with open(input_file, "rb") as f:
source = PdfFileReader(f, "rb")
for page in range(source.getNumPages()):
page = source.getPage(page)
content_object = page.getContents()
content = ContentStream(content_object, source)
for operands, operator in content.operations:
if operator == b_("Tf"):
font_size.append(int(operands[1]))
font_size = list(set(font_size))
wm_size = max(font_size)
f.close()
return wm_size
input_file = "doc_o.pdf"
output_file = "docdocdoc.pdf"
wm_size = font_size(input_file)
remove_watermark(input_file,wm_size,output_file)
4.小结
之前使用fitz的问题在于,分析使用单水印页面,文字段单独压缩容易识别,当整个页面整体对文字段压缩后,特征码随之改变,按单水印的字符就识别不了了;
目前使用pypdf2对pdf操作符进行识别更改字体样式,效果还可以,而且还有一些额外的功能待发掘。
**************************************
--2021.2.27晚
再稍等一下,单独调试单页水印的代码,可以实现
但是写完代码还是报错,好像是格式错了...
同时发现不同单页生成水印,特征码会变化...
--2021.2.28
Pypdf2也可以删文字水印,简书上有代码例子实际来自Stack Overflow,试了下会误删文字,导致页面变少
---2021.3.2
识别pdf中水印字体样式,进一步分析文字水印字体样式,将其字体大小改为0,可将可视水印去除 |