按坐标提取PDF文本

6
我想知道在Microsoft .NET中是否有一些PDF库,能够通过给定坐标来提取文本。
例如(伪代码):
PdfReader reader = new PdfReader();
reader.Load("file.pdf");

// Top, bottom, left, right in pixels or any other unit
string wholeText = reader.GetText(100, 150, 20, 50);

我尝试使用基于IKVM的PDFBox for .NET进行翻译,但没有成功,并且该软件似乎非常过时且文档不全。或许有人用PDFBox、iTextSharp或其他开源库做过这个事情,可以给我一些提示吗?谢谢!

难道你不认为缩放视图会改变指定坐标处的文本吗?基于表示中数据位置来提取数据,特别是当它可能会发生变化时,似乎不是库开发人员会费心实现的功能。 - Maxim V. Pavlov
不知道有哪个开源库能够胜任这项任务... 如果商业库是一个选项,我可以提供一两个链接... - Yahia
@Maxim 你说得对,但我的项目将有一个固定大小的PDF查看器,所以我认为这不是你所说的情况。例如,在Adobe Reader中,当您选择像图像这样的东西并进行缩放和缩小时,选择也会被调整大小。也许可以通过某个库来实现这一点。事实上,Apache PDFBox有一些类似于提供矩形选择区域的功能,这意味着我并不像你想象的那么疯狂:D - Matías Fidemraizer
@Yahia,这将取决于定价,但请在评论中给我这些提示,我会看一下。 - Matías Fidemraizer
6个回答

8

谢谢大家的帮助。

我使用了 Apache 的 PDFBox 在 IKVM 编译之上,以下是最终代码:

PDDocument doc = PDDocument.load(@"c:\invoice.pdf");

PDFTextStripperByArea stripper = new PDFTextStripperByArea();
stripper.addRegion("testRegion", new java.awt.Rectangle(0, 10, 100, 100));
stripper.extractRegions((PDPage)doc.getDocumentCatalog().getAllPages().get(0));

string text = stripper.getTextForRegion("testRegion");

它的工作效果非常好。

无论如何,感谢您,我希望我的答案能帮助其他人。如果您需要更多细节,请在此处发表评论,我将更新此答案。


我想在pdfsharp或c#中实现同样的功能,请帮帮我。 - Vivek Parikh
1
要使用上面答案中的代码,您必须设置IKVM。虽然对我来说需要一些时间进行调查,但这很简单。您需要引用以下库:IKVM.OpenJDK.Core.dll、IKVM.OpenJDK.SwingAWT.dll、pdfbox-1.8.2.dll(通过ikvmc -target:library pdfbox-1.8.2.jar命令获取),IKVM.OpenJDK.Util.dll和IKVM.Runtime.dll。 - Alexander Smirnov
在Java中,这对我非常有效。唯一的问题是我必须试错来获取我想要提取的文本的坐标。有什么想法可以从PDF中提取它们吗?尝试了SO上的几个选项,但效果不太好。(https://dev59.com/G2ox5IYBdhLWcg3wyHTc) - Gaurav Parek

3
希望这能对你有所帮助(以及其他使用ABCPDF的人)!虽然它不是开源的。我今天早些时候通过循环遍历PDF中可用的字段来完成此操作。这意味着您使用的PDF需要正确创建,并且您需要知道要获取文本的字段名称(您可以通过添加断点并循环遍历可用字段来解决此问题)。
WebSupergoo.ABCpdf6.Doc newPDF = new WebSupergoo.ABCpdf6.Doc();
newPDF.Read("existing_file.pdf");

foreach ( WebSupergoo.ABCpdf6.Objects.Field field in newPDF.Form.Fields )
{
    if ( field.Name == "Text1" )
    {
        // update "Text1"
        field.Value = "new value for Text1";
    }
}

newPDF.Save("new_file.pdf");

newPDF.Clear();

在这个例子中,“Text1”是正在更新的字段的名称。请注意,我还提供了一个保存更新字段的示例。
希望这至少让您了解如何解决这个问题。

嗯,我的问题不是迭代字段。我需要提供坐标并获取“矩形的情况”。抱歉。但还是谢谢。 - Matías Fidemraizer
字段对象公开了一个属性“Rect”。如果您知道他们点击的位置,可以通过查看Rect的顶部/底部/右侧/左侧来返回与坐标匹配的字段。可能有使用不同库的更好方法,但如果您卡住了,这种方法可能有效。 - Ben Pearson
好的,知道了,这是另一个资源。我正在寻找一些更任意选择的库,但没关系。 - Matías Fidemraizer

3
这应该可以工作:
RenderFilter[] filters = new RenderFilter[1];
LocationTextExtractionStrategy regionFilter = new LocationTextExtractionStrategy();
filters[0] = new RegionTextRenderFilter(new Rectangle(llx,lly,urx,ury));
FilteredTextRenderListener strategy = new FilteredTextRenderListener(regionFilter, filters);

String result = PdfTextExtractor.GetTextFromPage(pdfReader, i, strategy);
Console.WriteLine(result);

2
iText的RegionTextRenderFilter正是您所需要的。 因此,您需要像这样的东西(请原谅我的Java,但翻译应该很简单):
PdfReader reader = new PdfReader(path);

FilteredTextExtractionStrategy regionFilter = 
  new FilteredTextExtractionStrategy( new SimpleTextExtrationStrategy, 
                                      new RegionTextRenderFilter( someRect ) );
String regionText = PdfTextExtractor.getTextFromPage(reader, 0, regionFilter );

很好,知道还有另一种解决相同问题的选择,所以如果使用PDFBox for .NET有些问题,我会去看看。无论如何,为你的贡献点赞。 - Matías Fidemraizer
1
嘿,我正在尝试您的解决方案,但似乎 iTextSharp(.NET 版本)没有这样的策略... - Matías Fidemraizer
和Marias一样的问题--在.NET中如何实现这个? - Richard West

1

这段代码将在iText 7中工作

PdfReader reader = new PdfReader("D:/Sample2.pdf");
PdfDocument pdfDoc = new PdfDocument(reader);
Rectangle rect = new Rectangle(208, 508, 235, 519);
TextRegionEventFilter regionFilter = new 
TextRegionEventFilter(rect.SetBbox(208, 508, 235, 519));
ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
FilteredEventListener listener = new FilteredEventListener();
LocationTextExtractionStrategy extractionStrategy = listener.AttachEventListener(new LocationTextExtractionStrategy(), regionFilter);
new PdfCanvasProcessor(listener).ProcessPageContent(pdfDoc.GetPage(1));
String text = extractionStrategy.GetResultantText();

0

你可能想看一下这个示例。它使用了itextsharp。

var pdfFilename = @"PathToYourPDF\random.pdf";
var textToFind = "Lombok";
var pageNumber = 1;
var point = PdfTools.GetTextCoordinate(textToFind, pdfFilename , pageNumber);
Console.WriteLine($"{point.X},{point.Y}");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接