PDF识别文字、关键字,获取对应坐标,用于插入电子签名

*java识别pdf中的关键字,获取关键字坐标 *

今天遇到个需求,需要在pdf中识别关键字的坐标位置并插入电子签名(png,jpg),在网上找了很多的案例,发现不同的pdf识别出来效果不一样,有的pdf识别是一个文字一个文字,有的是一段文字一段文字。最终发现,由于pdf来源不同(word转换、excel转换、图片转换)导致识别的效果有所差异。

于是自己整理了一份案例,效果还算完美

效果展示

在这里插入图片描述

废话不多说
使用依赖:itextpdf-5.5.13.jar
常见itextpdf各个版本【0积分免费下载】 下载地址

  1. 新建DTO实体,用于接收返回的坐标信息
public class MatchItem {
    /**
     * 页数
     */
    private Integer pageNum;

    /**
     * X轴坐标
     */
    private Float x;

    /**
     * Y轴坐标
     */
    private Float y;

    /**
     * 宽度
     */
    private Float pageWidth;

    /**
     * 高度
     */
    private Float pageHeight;

    /**
     * 匹配到的文案
     */
    private String content;

    public Integer getPageNum() {
        return pageNum;
    }

    public void setPageNum(Integer pageNum) {
        this.pageNum = pageNum;
    }

    public Float getX() {
        return x;
    }

    public void setX(Float x) {
        this.x = x;
    }

    public Float getY() {
        return y;
    }

    public void setY(Float y) {
        this.y = y;
    }

    public Float getPageWidth() {
        return pageWidth;
    }

    public void setPageWidth(Float pageWidth) {
        this.pageWidth = pageWidth;
    }

    public Float getPageHeight() {
        return pageHeight;
    }

    public void setPageHeight(Float pageHeight) {
        this.pageHeight = pageHeight;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "MatchItem [pageNum=" + pageNum + ", x=" + x + ", y=" + y
                + ", pageWidth=" + pageWidth + ", pageHeight=" + pageHeight
                + ", content=" + content + "]";
    }

}

2.新建工具类,用处识别文字坐标

public class AutoMatch {

    public static List<MatchItem> matchPage(String fileName, String keyword) throws Exception {
        List<MatchItem> items = new ArrayList();
        PdfReader reader = new PdfReader(fileName);
        int pageSize = reader.getNumberOfPages();
        for (int page = 1; page <= pageSize; page++) {
            items.addAll(matchPage(reader, page, keyword));
        }
        return items;
    }

    public static List matchPage(PdfReader reader, Integer pageNumber, String keyword) throws Exception {
        KeyWordPositionListener renderListener = new KeyWordPositionListener();
        renderListener.setKeyword(keyword);
        PdfReaderContentParser parse = new PdfReaderContentParser(reader);
        Rectangle rectangle = reader.getPageSize(pageNumber);
        renderListener.setPageNumber(pageNumber);
        renderListener.setCurPageSize(rectangle);
        parse.processContent(pageNumber, renderListener);
        return findKeywordItems(renderListener, keyword);
    }

    public static List findKeywordItems(KeyWordPositionListener renderListener, String keyword) {
        //先判断本页中是否存在关键词
        //所有块LIST
        List<MatchItem> allItems = renderListener.getAllItems();
        StringBuffer sbtemp = new StringBuffer("");
        //将一页中所有的块内容连接起来组成一个字符串。
        for (MatchItem item : allItems) {
            sbtemp.append(item.getContent());
        }
        //一页组成的字符串没有关键词,直接return
        if (sbtemp.toString().indexOf(keyword) == -1) {
            return renderListener.getMatches();
        }
        //第一种情况:关键词与块内容完全匹配的项
        List matches = renderListener.getMatches();

        //第二种情况:多个块内容拼成一个关键词,则一个一个来匹配,组装成一个关键词
        sbtemp = new StringBuffer("");
        List tempItems = new ArrayList();
        for (MatchItem item : allItems) {
            //1,关键词中存在某块 2,拼装的连续的块=关键词 3,避开某个块完全匹配关键词
            //关键词 中国移动 而块为 中 ,国,移动
            //关键词 中华人民 而块为中,华人民共和国 这种情况解决不了,也不允许存在

            if (keyword.indexOf(item.getContent()) != -1 && !keyword.equals(item.getContent())) {
                System.out.println(item.getContent());
                tempItems.add(item);
                sbtemp.append(item.getContent());
                //如果暂存的字符串和关键词 不再匹配时
                if (keyword.indexOf(sbtemp.toString()) == -1) {
                    sbtemp = new StringBuffer(item.getContent());
                    tempItems.clear();
                    tempItems.add(item);
                }
                //暂存的字符串正好匹配到关键词时
                if (sbtemp.toString().equalsIgnoreCase(keyword)) {
                    MatchItem tmpitem = getRightItem(tempItems, keyword);
                    if (tmpitem != null) {
                        //得到匹配的项
                        matches.add(tmpitem);
                    }
                    //清空暂存的字符串
                    sbtemp = new StringBuffer("");
                    //清空暂存的LIST
                    tempItems.clear();
                    //继续查找
                    continue;
                }
            } else {
                //如果找不到则清空
                sbtemp = new StringBuffer("");
                tempItems.clear();
            }
        }
        //第三种情况:关键词存在块中
        for (MatchItem item : allItems) {
            if (item.getContent().indexOf(keyword) != -1 && !keyword.equals(item.getContent())) {
                matches.add(item);
            }
        }
        return matches;
    }

    public static MatchItem getRightItem(List<MatchItem> tempItems, String keyword) {
        for (MatchItem item : tempItems) {
            if (keyword.indexOf(item.getContent()) != -1 && !keyword.equals(item.getContent())) {
                return item;
            }
        }
        return null;
    }

3.新建pdf监听类,重写源码方法

public class KeyWordPositionListener implements RenderListener {
    private List<MatchItem> matches = new ArrayList<>();
    private List<MatchItem> allItems = new ArrayList<>();
    private Rectangle curPageSize;

    /**
     * 匹配的关键字
     */
    private String keyword;
    /**
     * 匹配的当前页
     */
    private Integer pageNumber;

    public void beginTextBlock() {
        //do nothing
    }

    public void renderText(TextRenderInfo renderInfo) {
        String content = renderInfo.getText();
        content = content.replace("<", "").replace("《", "").replace("(", "").replace("(", "").replace("\"", "").replace("'", "")
                .replace(">", "").replace("》", "").replace(")", "").replace(")", "").replace("、", "").replace(".", "")
                .replace(":", "").replace(":", "").replace(" ", "");
        Rectangle2D.Float textRectangle = renderInfo.getDescentLine().getBoundingRectange();
        MatchItem item = new MatchItem();
        item.setContent(content);
        item.setPageNum(pageNumber);
        item.setPageWidth(curPageSize.getWidth());
        item.setPageHeight(curPageSize.getHeight());
        item.setX((float)textRectangle.getX());
        item.setY((float)textRectangle.getY());
        if(!StringUtils.isEmpty(content)){
            if(content.equalsIgnoreCase(keyword)) {
                matches.add(item);
            }
        }else{
            item.setContent("空字符串");
        }
        allItems.add(item);//先保存所有的项
    }

    public void endTextBlock() {
        //do nothing
    }

    public void renderImage(ImageRenderInfo renderInfo) {
        //do nothing
    }

    /**
     * 设置需要匹配的当前页
     * @param pageNumber
     */
    public void setPageNumber(Integer pageNumber) {
        this.pageNumber = pageNumber;
    }

    /**
     * 设置需要匹配的关键字,忽略大小写
     * @param keyword
     */
    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    /**
     * 返回匹配的结果列表
     * @return
     */
    public List<MatchItem> getMatches() {
        return matches;
    }

    void setCurPageSize(Rectangle rect) {
        this.curPageSize = rect;
    }

    public List<MatchItem> getAllItems() {
        return allItems;
    }

    public void setAllItems(List<MatchItem> allItems) {
        this.allItems = allItems;
    }


}

4.编写测试案例

   public static void main(String[] args) throws Exception {
        List<MatchItem> matchItemList = matchPage("pdf路径", "需要匹配的文案");
    }

返回坐标后,就可通过文字对应的坐标信息插入电子签名了。

提示:插入签名的话一般需要向不同方向设置偏移量,调整到自己理想位置,直接对X坐标或Y坐标进行加减即可。

pdf插入图片可见另一个帖子
点击跳转

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个问题需要用到 iTextSharp 库来解决。首先,你需要安装该库并导入它。然后,你可以使用以下代码获取指定关键字坐标位置信息: ```c# using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using iTextSharp.text.pdf; using iTextSharp.text.pdf.parser; namespace PdfKeywordCoordinates { class Program { static void Main(string[] args) { string filename = @"C:\example.pdf"; // pdf 文件路径 string keyword = "example keyword"; // 指定关键字 using (PdfReader reader = new PdfReader(filename)) { for (int page = 1; page <= reader.NumberOfPages; page++) { ITextExtractionStrategy strategy = new LocationTextExtractionStrategy(); string currentText = PdfTextExtractor.GetTextFromPage(reader, page, strategy); if (currentText.Contains(keyword)) { var kwLocation = new List<RectAndText>(); var renderFilter = new RenderFilter[1]; renderFilter[0] = new RegionTextRenderFilter(new Rectangle(0, 0, 1000, 1000)); var textExtractionStrategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), renderFilter); PdfContentStreamProcessor processor = new PdfContentStreamProcessor(textExtractionStrategy); processor.ProcessContent(reader.GetPageContent(page)); kwLocation = ((LocationTextExtractionStrategy)textExtractionStrategy).GetLocations(); foreach (RectAndText rectAndText in kwLocation) { if (rectAndText.text.Contains(keyword)) { Console.WriteLine("Page: " + page + " X: " + rectAndText.rect.Left + " Y: " + rectAndText.rect.Bottom); } } } } } Console.ReadLine(); } } public class RectAndText { public iTextSharp.text.Rectangle rect; public String text; public RectAndText(iTextSharp.text.Rectangle rect, String text) { this.rect = rect; this.text = text; } } } ``` 这个代码将在指定的 PDF 文件中查找指定的关键字,并输出该关键字在每一页中的坐标位置信息。注意,这个代码是使用 C# 编写的,如果你使用的是 Python,你需要使用 Python 版本的 iTextSharp 库,并使用相应的语法来实现相同的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值