PDF 文档可以包含 "unreachable" 内容吗?
Can PDF documents contain "unreachable" content?
我正在调查 Java PDF 库。
我试过了
org.apache.pdfbox
File file = new File("file.pdf");
PDDocument document = PDDocument.load(file);
// Instantiate PDFTextStripper class
PDFTextStripper pdfStripper = new PDFTextStripper();
// Retrieving text from PDF document
String text = pdfStripper.getText(document);
System.out.println(text);
// Closing the document
document.close();
com.itextpdf.text.pdf
public static final String SRC = "file.pdf";
public static final String DEST = "streams";
public static void main(final String[] args) throws IOException {
File file = new File(DEST);
new BruteForce().parse(SRC, DEST);
}
public void parse(final String src, final String dest) throws IOException {
PdfReader reader = new PdfReader(src);
PdfObject obj;
for (int i = 1; i <= reader.getXrefSize(); i++) {
obj = reader.getPdfObject(i);
if ((obj != null) && obj.isStream()) {
PRStream stream = (PRStream) obj;
byte[] b;
try {
b = PdfReader.getStreamBytes(stream);
} catch (UnsupportedPdfException e) {
b = PdfReader.getStreamBytesRaw(stream);
}
FileOutputStream fos = new FileOutputStream(String.format(dest, i));
fos.write(b);
fos.flush();
fos.close();
} else {
final PdfDictionary pdfDictionary = (PdfDictionary) obj;
System.out.println("\t>>>>> " + pdfDictionary + "\t\t" + pdfDictionary.getKeys());
final Set<PdfName> pdfNames = pdfDictionary.getKeys();
for (final PdfName pdfName : pdfNames) {
final PdfObject pdfObject = pdfDictionary.get(pdfName);
final int type = pdfObject.type();
switch (type) {
case PdfObject.NULL:
System.out.println("\t NULL " + pdfObject);
break;
case PdfObject.BOOLEAN:
System.out.println("\t BOOLEAN " + pdfObject);
break;
case PdfObject.NUMBER:
System.out.println("\t NUMBER " + pdfObject);
break;
case PdfObject.STRING:
System.out.println("\t STRING " + pdfObject);
break;
case PdfObject.NAME:
System.out.println("\t NAME " + pdfObject);
break;
case PdfObject.ARRAY:
System.out.println("\t ARRAY " + pdfObject);
break;
case PdfObject.DICTIONARY:
System.out.println("\t DICTIONARY " + ((PdfDictionary)pdfObject).getKeys());
break;
case PdfObject.STREAM:
System.out.println("\t STREAM " + pdfObject);
break;
case PdfObject.INDIRECT:
System.out.println("\t INDIRECT " +pdfObject.getIndRef());
break;
default:
}
System.out.println("\t\t--- " + pdfObject.type());
}
}
}
}
com.snowtide.pdf
字符串 pdfFilePath = "file.pdf";
Document pdf = PDF.open(pdfFilePath);
final List<Annotation> annotations = pdf.getAllAnnotations();
for (final Annotation annotation : annotations) {
System.out.println(annotation.pageNumber());
}
System.out.println(pdf.getAttributeMap());
System.out.println(pdf.getAttributeKeys());
System.out.println("=============================");
StringBuilder text = new StringBuilder(1024);
pdf.pipe(new OutputTarget(text));
pdf.close();
System.out.println(text);
我可以提取所有可见的 PDF 内容,包括链接、文本和图像,除了出现在每个页面上的 "Watermark"。
PDF 文档可以包含 "unreachable" 内容吗?
没有办法从 PDF 文件中提取 ALL 内容吗?
更新
认为 "watermark" 是图像我尝试了此代码
File fileW = new File("file.pdf");
PDDocument document = PDDocument.load(fileW);
PDPageTree list = document.getPages();
for (PDPage page : list) {
PDResources pdResources = page.getResources();
for (COSName c : pdResources.getXObjectNames()) {
System.out.println("????? ::>>>" + c);
PDXObject o = pdResources.getXObject(c);
if (o instanceof org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject) {
File file = new File("Temp/" + System.nanoTime() + ".png");
ImageIO.write(((org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject) o).getImage(), "png", file);
} else {
}
}
}
PDF 确实包含作者的图像,但是这种方法无法达到 "watermark"。
OP提供的示例文档的页面内容流从第2页开始具有以下结构:
文本 header 行 "www.electrophoresis-journal.com Page X Electrophoresis":
BT
/F1 9.12 Tf
1 0 0 1 72.024 798.46 Tm
/GS7 gs
0 g
0 G
[(w)11(w)11(w)11(.)-12(e)-2(l)15(e)-2(c)23(t)-10(r)-8(o)26(pho)26(r)-8(e)-2(s)21(i)-10(s)] TJ
ET
[...]
BT
1 0 0 1 441.53 798.46 Tm
[(E)6(l)-10(e)-2(c)23(t)-10(r)-8(o)26(pho)26(r)-8(e)23(s)-5(i)15(s)] TJ
ET
BT
1 0 0 1 497.47 798.46 Tm
[( )] TJ
ET
BT
1 0 0 1 72.024 787.9 Tm
[( )] TJ
ET
可以使用普通的 iText 或 PDFBox 文本提取轻松提取此文本。
文本 multi-line 页脚 "Received: ... All rights reserved."
BT
1 0 0 1 72.024 109.7 Tm
[(R)9(e)-2(c)23(e)-2(i)-10(v)26(e)-2(d:)41( )] TJ
ET
[...]
BT
1 0 0 1 72.024 47.76 Tm
[(T)6(hi)-10(s)21( )-12(a)23(r)-8(t)15(i)-10(c)23(l)-10(e)23( )13(i)-10(s)21( )-12(pr)-8(o)26(t)15(e)-2(c)23(t)-10(e)-2(d)26( )-12(by)53( )-12(c)-2(o)26(p)-25(y)53(r)-8(i)-10(g)26(ht)-10(.)-12( )-12(A)38(l)-10(l)15( )13(r)-8(i)-10(g)26(ht)15(s)-5( )13(r)-8(e)23(s)-5(e)-2(r)-8(v)26(e)-2(d)26(.)] TJ
ET
BT
1 0 0 1 278.52 47.76 Tm
[( )] TJ
ET
BT
1 0 0 1 72.024 37.2 Tm
[( )] TJ
ET
也可以使用普通的 iText 或 PDFBox 文本提取轻松提取此文本。
一组PDF路径创建和填充操作使用自定义图形状态形成页面左侧透明"Accepted Article"书写:
/GS8 gs
0 g
39.605 266.51 m
39.605 261.29 39.605 256.06 39.605 250.84 c
42.197 249.94 44.776 248.99 47.367 248.09 c
49.296 247.41 50.704 247.08 51.649 247.08 c
52.413 247.08 53.058 247.38 53.609 247.97 c
54.191 248.54 54.548 249.82 54.729 251.77 c
55.18 251.77 55.624 251.77 56.075 251.77 c
56.075 247.51 56.075 243.26 56.075 239.02 c
55.624 239.02 55.18 239.02 54.729 239.02 c
54.36 240.72 53.903 241.8 53.314 242.3 c
52.144 243.3 49.809 244.47 46.247 245.67 c
32.719 250.33 19.286 255.25 5.7645 259.91 c
5.7645 260.26 5.7645 260.61 5.7645 260.95 c
19.43 265.57 33.014 270.43 46.679 275.05 c
49.984 276.16 52.075 277.24 53.064 278.15 c
54.053 279.06 54.623 280.36 54.729 282 c
55.18 282 55.624 282 56.075 282 c
56.075 276.68 56.075 271.35 56.075 266.03 c
55.624 266.03 55.18 266.03 54.729 266.03 c
54.623 267.64 54.303 268.75 53.753 269.31 c
53.202 269.88 52.519 270.15 51.718 270.15 c
50.666 270.15 48.97 269.75 46.679 268.95 c
44.319 268.15 41.971 267.31 39.605 266.51 c
h
36.92 265.67 m
30.284 263.43 23.686 261.05 17.045 258.81 c
23.686 256.5 30.284 254.07 36.92 251.77 c
36.92 256.4 36.92 261.04 36.92 265.67 c
h
f*
[...]
35.361 630.34 m
40.294 630.31 44.156 631.32 46.967 633.29 c
49.784 635.27 51.18 637.63 51.18 640.31 c
51.18 642.1 50.573 643.67 49.364 645 c
48.156 646.3 46.141 647.43 43.236 648.31 c
43.48 648.62 43.712 648.93 43.962 649.24 c
47.261 648.83 50.253 647.57 52.989 645.6 c
55.731 643.62 57.089 641.06 57.089 638.05 c
57.089 634.76 55.549 631.92 52.413 629.63 c
49.302 627.3 45.158 626.1 39.899 626.1 c
34.203 626.1 29.802 627.33 26.585 629.71 c
23.405 632.07 21.834 635.12 21.834 638.73 c
21.834 641.8 23.048 644.34 25.496 646.28 c
27.981 648.22 31.267 649.24 35.361 649.24 c
35.361 642.94 35.361 636.64 35.361 630.34 c
h
33.258 630.34 m
33.258 634.56 33.258 638.78 33.258 643 c
31.117 642.91 29.633 642.7 28.763 642.37 c
27.417 641.87 26.341 641.14 25.571 640.16 c
24.801 639.19 24.406 638.13 24.406 637.06 c
24.406 635.42 25.158 633.91 26.729 632.64 c
28.306 631.34 30.466 630.55 33.258 630.34 c
h
f*
(我引用的说明绘制了初始 'A' 和最终 'e'。)
这篇文章无法使用普通的 iText 或 PDFBox 文本提取来提取,因为它既不是使用文本指令绘制的,也没有用 ActualText 条目标记。 (后者可以使用自定义的 iText 或 PDFBox 文本提取来识别。)
但是您可以将此文字提取为路径创建和绘图命令的序列,它包含使用 iText ExtRenderListener
接口的实现或 PDFBox PDFGraphicsStreamEngine
.[=18 的子类=]
文章的实际文字内容,不透明,使用文字绘制说明,例如
BT
/F2 10.08 Tf
1 0 0 1 72.024 760.78 Tm
/GS7 gs
0 g
[(H)-7(I)8(G)16(H)-7( )-106(TH)-6(R)32(O)-7(U)8(G)16(H)-7(P)16(U)8(T )-106(M)-7(U)8(LTI)] TJ
ET
BT
1 0 0 1 212.98 760.78 Tm
[(-)] TJ
ET
BT
1 0 0 1 216.1 760.78 Tm
[(O)-7(R)8(G)-7(A)8(N)32( )-130(M)15(ETA)32(BO)-6(LO)16(M)-7(I)8(C)8(S)8( )-130(I)8(N)8( )-106(TH)-6(E)24( )-130(A)8(P)16(P)16(/)-7(P)16(S)8(1 )-106(M)-7(O)-7(U)8(S)8(E)24( )-130(M)15(O)-7(D)8(EL)24( )-106(O)-7(F)16( )] TJ
ET
也可以使用普通的 iText 或 PDFBox 文本提取轻松提取此文本。
因此,关于 OP 的问题,
I can extract all visible PDF content including links, text, and images apart from what appears to be a "Watermark" that appears on every page.
Can PDF documents contain "unreachable" content?
该内容不是"unreachable",它只是不是使用文本绘制指令绘制的文本,而是像任意形状一样绘制的文本。
Is there no way to extract ALL content from a PDF file?
您可以提取该内容,但不是作为文本,而是作为 collection 路径创建和绘图说明。每当您怀疑此类指令实际绘制字母形状时,您可以尝试通过将这些路径呈现为位图并应用 OCR 来确定文本。
我正在调查 Java PDF 库。
我试过了
org.apache.pdfbox
File file = new File("file.pdf");
PDDocument document = PDDocument.load(file);
// Instantiate PDFTextStripper class
PDFTextStripper pdfStripper = new PDFTextStripper();
// Retrieving text from PDF document
String text = pdfStripper.getText(document);
System.out.println(text);
// Closing the document
document.close();
com.itextpdf.text.pdf
public static final String SRC = "file.pdf";
public static final String DEST = "streams";
public static void main(final String[] args) throws IOException {
File file = new File(DEST);
new BruteForce().parse(SRC, DEST);
}
public void parse(final String src, final String dest) throws IOException {
PdfReader reader = new PdfReader(src);
PdfObject obj;
for (int i = 1; i <= reader.getXrefSize(); i++) {
obj = reader.getPdfObject(i);
if ((obj != null) && obj.isStream()) {
PRStream stream = (PRStream) obj;
byte[] b;
try {
b = PdfReader.getStreamBytes(stream);
} catch (UnsupportedPdfException e) {
b = PdfReader.getStreamBytesRaw(stream);
}
FileOutputStream fos = new FileOutputStream(String.format(dest, i));
fos.write(b);
fos.flush();
fos.close();
} else {
final PdfDictionary pdfDictionary = (PdfDictionary) obj;
System.out.println("\t>>>>> " + pdfDictionary + "\t\t" + pdfDictionary.getKeys());
final Set<PdfName> pdfNames = pdfDictionary.getKeys();
for (final PdfName pdfName : pdfNames) {
final PdfObject pdfObject = pdfDictionary.get(pdfName);
final int type = pdfObject.type();
switch (type) {
case PdfObject.NULL:
System.out.println("\t NULL " + pdfObject);
break;
case PdfObject.BOOLEAN:
System.out.println("\t BOOLEAN " + pdfObject);
break;
case PdfObject.NUMBER:
System.out.println("\t NUMBER " + pdfObject);
break;
case PdfObject.STRING:
System.out.println("\t STRING " + pdfObject);
break;
case PdfObject.NAME:
System.out.println("\t NAME " + pdfObject);
break;
case PdfObject.ARRAY:
System.out.println("\t ARRAY " + pdfObject);
break;
case PdfObject.DICTIONARY:
System.out.println("\t DICTIONARY " + ((PdfDictionary)pdfObject).getKeys());
break;
case PdfObject.STREAM:
System.out.println("\t STREAM " + pdfObject);
break;
case PdfObject.INDIRECT:
System.out.println("\t INDIRECT " +pdfObject.getIndRef());
break;
default:
}
System.out.println("\t\t--- " + pdfObject.type());
}
}
}
}
com.snowtide.pdf
字符串 pdfFilePath = "file.pdf";
Document pdf = PDF.open(pdfFilePath);
final List<Annotation> annotations = pdf.getAllAnnotations();
for (final Annotation annotation : annotations) {
System.out.println(annotation.pageNumber());
}
System.out.println(pdf.getAttributeMap());
System.out.println(pdf.getAttributeKeys());
System.out.println("=============================");
StringBuilder text = new StringBuilder(1024);
pdf.pipe(new OutputTarget(text));
pdf.close();
System.out.println(text);
我可以提取所有可见的 PDF 内容,包括链接、文本和图像,除了出现在每个页面上的 "Watermark"。
PDF 文档可以包含 "unreachable" 内容吗?
没有办法从 PDF 文件中提取 ALL 内容吗?
更新
认为 "watermark" 是图像我尝试了此代码
File fileW = new File("file.pdf");
PDDocument document = PDDocument.load(fileW);
PDPageTree list = document.getPages();
for (PDPage page : list) {
PDResources pdResources = page.getResources();
for (COSName c : pdResources.getXObjectNames()) {
System.out.println("????? ::>>>" + c);
PDXObject o = pdResources.getXObject(c);
if (o instanceof org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject) {
File file = new File("Temp/" + System.nanoTime() + ".png");
ImageIO.write(((org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject) o).getImage(), "png", file);
} else {
}
}
}
PDF 确实包含作者的图像,但是这种方法无法达到 "watermark"。
OP提供的示例文档的页面内容流从第2页开始具有以下结构:
文本 header 行 "www.electrophoresis-journal.com Page X Electrophoresis":
BT /F1 9.12 Tf 1 0 0 1 72.024 798.46 Tm /GS7 gs 0 g 0 G [(w)11(w)11(w)11(.)-12(e)-2(l)15(e)-2(c)23(t)-10(r)-8(o)26(pho)26(r)-8(e)-2(s)21(i)-10(s)] TJ ET [...] BT 1 0 0 1 441.53 798.46 Tm [(E)6(l)-10(e)-2(c)23(t)-10(r)-8(o)26(pho)26(r)-8(e)23(s)-5(i)15(s)] TJ ET BT 1 0 0 1 497.47 798.46 Tm [( )] TJ ET BT 1 0 0 1 72.024 787.9 Tm [( )] TJ ET
可以使用普通的 iText 或 PDFBox 文本提取轻松提取此文本。
文本 multi-line 页脚 "Received: ... All rights reserved."
BT 1 0 0 1 72.024 109.7 Tm [(R)9(e)-2(c)23(e)-2(i)-10(v)26(e)-2(d:)41( )] TJ ET [...] BT 1 0 0 1 72.024 47.76 Tm [(T)6(hi)-10(s)21( )-12(a)23(r)-8(t)15(i)-10(c)23(l)-10(e)23( )13(i)-10(s)21( )-12(pr)-8(o)26(t)15(e)-2(c)23(t)-10(e)-2(d)26( )-12(by)53( )-12(c)-2(o)26(p)-25(y)53(r)-8(i)-10(g)26(ht)-10(.)-12( )-12(A)38(l)-10(l)15( )13(r)-8(i)-10(g)26(ht)15(s)-5( )13(r)-8(e)23(s)-5(e)-2(r)-8(v)26(e)-2(d)26(.)] TJ ET BT 1 0 0 1 278.52 47.76 Tm [( )] TJ ET BT 1 0 0 1 72.024 37.2 Tm [( )] TJ ET
也可以使用普通的 iText 或 PDFBox 文本提取轻松提取此文本。
一组PDF路径创建和填充操作使用自定义图形状态形成页面左侧透明"Accepted Article"书写:
/GS8 gs 0 g 39.605 266.51 m 39.605 261.29 39.605 256.06 39.605 250.84 c 42.197 249.94 44.776 248.99 47.367 248.09 c 49.296 247.41 50.704 247.08 51.649 247.08 c 52.413 247.08 53.058 247.38 53.609 247.97 c 54.191 248.54 54.548 249.82 54.729 251.77 c 55.18 251.77 55.624 251.77 56.075 251.77 c 56.075 247.51 56.075 243.26 56.075 239.02 c 55.624 239.02 55.18 239.02 54.729 239.02 c 54.36 240.72 53.903 241.8 53.314 242.3 c 52.144 243.3 49.809 244.47 46.247 245.67 c 32.719 250.33 19.286 255.25 5.7645 259.91 c 5.7645 260.26 5.7645 260.61 5.7645 260.95 c 19.43 265.57 33.014 270.43 46.679 275.05 c 49.984 276.16 52.075 277.24 53.064 278.15 c 54.053 279.06 54.623 280.36 54.729 282 c 55.18 282 55.624 282 56.075 282 c 56.075 276.68 56.075 271.35 56.075 266.03 c 55.624 266.03 55.18 266.03 54.729 266.03 c 54.623 267.64 54.303 268.75 53.753 269.31 c 53.202 269.88 52.519 270.15 51.718 270.15 c 50.666 270.15 48.97 269.75 46.679 268.95 c 44.319 268.15 41.971 267.31 39.605 266.51 c h 36.92 265.67 m 30.284 263.43 23.686 261.05 17.045 258.81 c 23.686 256.5 30.284 254.07 36.92 251.77 c 36.92 256.4 36.92 261.04 36.92 265.67 c h f* [...] 35.361 630.34 m 40.294 630.31 44.156 631.32 46.967 633.29 c 49.784 635.27 51.18 637.63 51.18 640.31 c 51.18 642.1 50.573 643.67 49.364 645 c 48.156 646.3 46.141 647.43 43.236 648.31 c 43.48 648.62 43.712 648.93 43.962 649.24 c 47.261 648.83 50.253 647.57 52.989 645.6 c 55.731 643.62 57.089 641.06 57.089 638.05 c 57.089 634.76 55.549 631.92 52.413 629.63 c 49.302 627.3 45.158 626.1 39.899 626.1 c 34.203 626.1 29.802 627.33 26.585 629.71 c 23.405 632.07 21.834 635.12 21.834 638.73 c 21.834 641.8 23.048 644.34 25.496 646.28 c 27.981 648.22 31.267 649.24 35.361 649.24 c 35.361 642.94 35.361 636.64 35.361 630.34 c h 33.258 630.34 m 33.258 634.56 33.258 638.78 33.258 643 c 31.117 642.91 29.633 642.7 28.763 642.37 c 27.417 641.87 26.341 641.14 25.571 640.16 c 24.801 639.19 24.406 638.13 24.406 637.06 c 24.406 635.42 25.158 633.91 26.729 632.64 c 28.306 631.34 30.466 630.55 33.258 630.34 c h f*
(我引用的说明绘制了初始 'A' 和最终 'e'。)
这篇文章无法使用普通的 iText 或 PDFBox 文本提取来提取,因为它既不是使用文本指令绘制的,也没有用 ActualText 条目标记。 (后者可以使用自定义的 iText 或 PDFBox 文本提取来识别。)
但是您可以将此文字提取为路径创建和绘图命令的序列,它包含使用 iText
ExtRenderListener
接口的实现或 PDFBoxPDFGraphicsStreamEngine
.[=18 的子类=]文章的实际文字内容,不透明,使用文字绘制说明,例如
BT /F2 10.08 Tf 1 0 0 1 72.024 760.78 Tm /GS7 gs 0 g [(H)-7(I)8(G)16(H)-7( )-106(TH)-6(R)32(O)-7(U)8(G)16(H)-7(P)16(U)8(T )-106(M)-7(U)8(LTI)] TJ ET BT 1 0 0 1 212.98 760.78 Tm [(-)] TJ ET BT 1 0 0 1 216.1 760.78 Tm [(O)-7(R)8(G)-7(A)8(N)32( )-130(M)15(ETA)32(BO)-6(LO)16(M)-7(I)8(C)8(S)8( )-130(I)8(N)8( )-106(TH)-6(E)24( )-130(A)8(P)16(P)16(/)-7(P)16(S)8(1 )-106(M)-7(O)-7(U)8(S)8(E)24( )-130(M)15(O)-7(D)8(EL)24( )-106(O)-7(F)16( )] TJ ET
也可以使用普通的 iText 或 PDFBox 文本提取轻松提取此文本。
因此,关于 OP 的问题,
I can extract all visible PDF content including links, text, and images apart from what appears to be a "Watermark" that appears on every page.
Can PDF documents contain "unreachable" content?
该内容不是"unreachable",它只是不是使用文本绘制指令绘制的文本,而是像任意形状一样绘制的文本。
Is there no way to extract ALL content from a PDF file?
您可以提取该内容,但不是作为文本,而是作为 collection 路径创建和绘图说明。每当您怀疑此类指令实际绘制字母形状时,您可以尝试通过将这些路径呈现为位图并应用 OCR 来确定文本。