- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想用一个单词替换任何空列;例如,提取 Pdf 数据时出现单词BLK。
下表是预期表和实际结果的示例。
原始表
+--------------------------------------+
|# |NAME |TEL |GENDER |
|---------------------------|----------|
|1 |JOHN |096587498 |M |
|2 |VILLA | |F |
+--------------------------------------+
预期结果
# NAME TEL GENDER
1 JOHN 096587498 M
2 VILLA BLK F
实际结果
# NAME TEL GENDER
1 JOHN 096587498 M
2 VILLA F
实际结果来自PDFTextStripper类。
最佳答案
PDFTextStripper
看不到 PDF 中的图形线,它只能看到文本字符。因此,在第 2 行中,它会看到“2”、“Villa”和“F”,中间有间隙。因此,仅靠这个类(class),你不会得到你想要的。
一般来说,使用 PDFBox 有以下选项:
您可以首先尝试通过解析页面的 vector 图形指令来识别 PDF 中的表格单元格区域,然后逐个单元格地提取文本。
This answer为此提供了概念验证。注意:这个答案重点关注该问题的OP提供的示例文档。特别是,它希望将线条绘制为细实心矩形;对于通用解决方案,需要扩展收集表格线的代码,以识别以其他方式绘制的线。
这种方法显然需要用行(或者通过扩展或者用背景颜色或类似的东西来划分)表格的行和列;但情况并非总是如此。
对于您的示例文档,代码可以开箱即用:
[A1] #
[A2] Name
[A3] Tel
[A4] Gender
[B1] 1
[B2] John
[B3] 096875959
[B4] M
[C1] 2
[C2] Villa
[C3]
[C4] F
(ExtractBoxedText测试testExtractBoxedTextsTestWPhromma
的输出)
您可以提取尝试反射(reflect) PDF 布局的文本。如果您知道相关表格的总体布局(第 n 列从这里到那里...),您可以导出表格单元格内容。
This answer为布局感知文本提取提供了概念验证。请注意,代码基于 PDFBox 1.8.x,可能需要进行一些调整。
此方法需要了解表格列布局;这并不总是给出。
对于您的示例文档,代码可以开箱即用:
# Name Tel Gender
1 John 096875959 M
2 Villa F
(ExtractTextWithLayout测试testExtractTestWPhromma
的输出)
对于带标签的 PDF,您可以尝试提取文本,包括反射(reflect)表格结构的标签(如果标签正确)。
随着您的示例文档被标记,我将在下面展示一个快速而肮脏的概念证明。
此方法需要对 PDF 进行正确标记;但情况并非总是如此。
如果您的 PDF 已正确标记,您可以提取包括标记标签的内容,如下所示:
PDDocument document = PDDocument.load(SOURCE);
Map<PDPage, Map<Integer, PDMarkedContent>> markedContents = new HashMap<>();
for (PDPage page : document.getPages()) {
PDFMarkedContentExtractor extractor = new PDFMarkedContentExtractor();
extractor.processPage(page);
Map<Integer, PDMarkedContent> theseMarkedContents = new HashMap<>();
markedContents.put(page, theseMarkedContents);
for (PDMarkedContent markedContent : extractor.getMarkedContents()) {
theseMarkedContents.put(markedContent.getMCID(), markedContent);
}
}
PDStructureNode root = document.getDocumentCatalog().getStructureTreeRoot();
showStructure(root, markedContents);
( ExtractMarkedContent 测试 testExtractTestWPhromma
)
使用这两个辅助方法
void showStructure(PDStructureNode node, Map<PDPage, Map<Integer, PDMarkedContent>> markedContents) {
String structType = null;
PDPage page = null;
if (node instanceof PDStructureElement) {
PDStructureElement element = (PDStructureElement) node;
structType = element.getStructureType();
page = element.getPage();
}
Map<Integer, PDMarkedContent> theseMarkedContents = markedContents.get(page);
System.out.printf("<%s>\n", structType);
for (Object object : node.getKids()) {
if (object instanceof COSArray) {
for (COSBase base : (COSArray) object) {
if (base instanceof COSDictionary) {
showStructure(PDStructureNode.create((COSDictionary) base), markedContents);
} else if (base instanceof COSNumber) {
showContent(((COSNumber)base).intValue(), theseMarkedContents);
} else {
System.out.printf("?%s\n", base);
}
}
} else if (object instanceof PDStructureNode) {
showStructure((PDStructureNode) object, markedContents);
} else if (object instanceof Integer) {
showContent((Integer)object, theseMarkedContents);
} else {
System.out.printf("?%s\n", object);
}
}
System.out.printf("</%s>\n", structType);
}
void showContent(int mcid, Map<Integer, PDMarkedContent> theseMarkedContents) {
PDMarkedContent markedContent = theseMarkedContents != null ? theseMarkedContents.get(mcid) : null;
List<Object> contents = markedContent != null ? markedContent.getContents() : Collections.emptyList();
StringBuilder textContent = new StringBuilder();
for (Object object : contents) {
if (object instanceof TextPosition) {
textContent.append(((TextPosition)object).getUnicode());
} else {
textContent.append("?" + object);
}
}
System.out.printf("%s\n", textContent);
}
(ExtractMarkedContent辅助方法)
示例 PDF 的输出
是
<null>
<Document>
<Table>
<THead>
<TR>
<TH>
<P>
#
</P>
</TH>
<TH>
<P>
Name
</P>
</TH>
<TH>
<P>
Tel
</P>
</TH>
<TH>
<P>
Gender
</P>
</TH>
</TR>
</THead>
<TBody>
<TR>
<TH>
<P>
1
</P>
</TH>
<TD>
<P>
John
</P>
</TD>
<TD>
<P>
096875959
</P>
</TD>
<TD>
<P>
M
</P>
</TD>
</TR>
<TR>
<TH>
<P>
2
</P>
</TH>
<TD>
<P>
Villa
</P>
</TD>
<TD>
<P>
</P>
</TD>
<TD>
<P>
F
</P>
</TD>
</TR>
</TBody>
</Table>
<P>
</P>
</Document>
</null>
您认识到空单元格:
<TD>
<P>
</P>
</TD>
此概念验证提取到标准输出。显然,您可以选择在字符串生成器或流中收集数据,或者可以填充 <Table>
数据立即进入自定义结构,它们毕竟已经在单元格中分开。
注意:这只是一个概念验证。代码输出这样的数据 System.out.printf("?%s\n", ...);
,可能需要一些特定的处理。其他边界条件也可能没有得到充分考虑。 (实际上,我实现它只是为了正确提取示例 PDF 的内容。)
关于java - 如何使用 PDFBox 从 PDF 中提取数据时用单词替换空格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54956720/
抱歉,标题不准确,但我的问题是:我正在尝试在代码隐藏中使用 css 设置背景图像,我想向该图像添加线性渐变,类似这样: Image1.Style["background-image"] = "line
我使用 DI 编写了一个大型应用程序。该应用程序由初始化时的 Bootstrap 组成,其中注入(inject)了大多数依赖项。一切皆好。 但是,有些服务* 我不能简单地到处注入(inject)。 一
当 sbt 使用 SbtOneJar 插件构建 OneJar 文件时,它为构建的 jar 提供名称 [name]_[scala-version]-[version]-one-jar.jar,其中 na
我使用的是 Bootstrap 3.0 及其网格系统,并且在我的页面上有两个 div,一个在另一个上面。 我想让用户能够切换 View ,这样这些 div 将一个放在一边另一个(点击按钮)。我可以仅使
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
目标是从 mkv 生成 HLS 兼容的 MPEGTS 片段,使用 -c:v copy 复制视频,但对音频进行转码。 但是,由于在输入搜索( -ss )时,ffmpeg 会搜索关键帧(对我来说,这似乎是
我正在使用 cffile action="upload" 将名称中包含空格的文件上传到 Amazon S3 .文件名为 burger+beans n beetroot.jpg .如您所见,该名称包含空
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Parsing blank XML tags with LXML and Python 给定以下 XML 文
我安装了 Visual Studio 2012 v3 和 git 扩展。 I want to change the default merge tool to winmerge but it seem
我是一名优秀的程序员,十分优秀!