iText7如何根据Rectangle信息提取对应PDF文本?
解决iText根据Rectangle精准提取文本的问题
问题根源
PDF中的文本通常以文本块为单位存储和绘制,即使你的正则匹配定位到了目标文本(比如"bbb")的矩形区域,如果该文本和前后内容属于同一个文本块,常规的区域提取逻辑会返回整个文本块的内容(比如"aaa-bbb-ccc")。
解决方案:自定义字符级文本提取策略
通过自定义文本提取策略,逐个检查每个字符的边界框是否落在目标Rectangle内,只保留符合条件的字符,实现精准提取。
步骤1:创建字符位置跟踪策略
继承LocationTextExtractionStrategy,记录每个字符的边界框和内容:
import com.itextpdf.kernel.geom.Rectangle; import com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo; import com.itextpdf.kernel.pdf.canvas.parser.listener.LocationTextExtractionStrategy; import java.util.ArrayList; import java.util.List; class CharacterPositionTrackingStrategy extends LocationTextExtractionStrategy { private final List<CharacterInfo> characterInfos = new ArrayList<>(); @Override public void renderText(TextRenderInfo renderInfo) { super.renderText(renderInfo); // 遍历每个字符,记录位置和文本 for (TextRenderInfo charInfo : renderInfo.getCharacterRenderInfos()) { Rectangle charRect = charInfo.getDescentLine().getBoundingRectangle(); characterInfos.add(new CharacterInfo(charRect, charInfo.getText())); } } public List<CharacterInfo> getCharacterInfos() { return characterInfos; } public static class CharacterInfo { private final Rectangle rect; private final String text; public CharacterInfo(Rectangle rect, String text) { this.rect = rect; this.text = text; } public Rectangle getRect() { return rect; } public String getText() { return text; } } }
步骤2:提取目标区域内的文本
使用上述策略提取页面所有字符的位置,再筛选出落在目标Rectangle内的字符:
import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfReader; import com.itextpdf.kernel.pdf.canvas.parser.PdfTextExtractor; import java.io.IOException; public class PreciseTextExtractor { public static String extractTextInTargetRect(PdfDocument pdfDoc, int pageNumber, Rectangle targetRect) throws IOException { CharacterPositionTrackingStrategy strategy = new CharacterPositionTrackingStrategy(); // 提取页面文本并跟踪所有字符位置 PdfTextExtractor.getTextFromPage(pdfDoc.getPage(pageNumber), strategy); StringBuilder result = new StringBuilder(); for (CharacterPositionTrackingStrategy.CharacterInfo charInfo : strategy.getCharacterInfos()) { Rectangle charRect = charInfo.getRect(); // 判断字符矩形与目标矩形是否重叠(可根据需求调整判断逻辑) if (targetRect.intersects(charRect)) { result.append(charInfo.getText()); } } return result.toString(); } public static void main(String[] args) throws IOException { try (PdfReader reader = new PdfReader("your-input.pdf"); PdfDocument pdfDoc = new PdfDocument(reader)) { // 替换为iTextSweep返回的目标Rectangle Rectangle targetRectangle = new Rectangle(/* x, y, width, height */); String preciseText = extractTextInTargetRect(pdfDoc, 1, targetRectangle); System.out.println(preciseText); } } }
注意事项
- 坐标一致性:确保目标Rectangle的坐标符合PDF的坐标系(左下角为原点(0,0)),iTextSweep返回的Rectangle默认是符合该规则的。
- 重叠判断逻辑:示例中使用
intersects判断字符矩形与目标矩形是否有重叠,你可以根据需求改为contains(字符完全在目标区域内),或自定义重叠比例阈值,进一步提升精准度。 - 性能考量:如果处理大页数的PDF,字符级遍历会增加一定开销,但对于精准提取需求来说是必要的。
内容的提问来源于stack exchange,提问作者Haolin Liu
相关产品推荐
相关产品推荐

