PDFJS 在转换为文本的 pdf 表单上丢失复选标记

问题描述 投票:0回答:2

我一直在使用这些帖子中的代码改编版:

nodejs 中的 PDF 到文本提取器,无需操作系统依赖

pdfjs:使用正确的换行符/空格从 pdf 中获取原始文本

将 pdf 文件转换为文本:

import pdfjsLib from 'pdfjs-dist/legacy/build/pdf.js';

import {
    TextItem,
    DocumentInitParameters,
} from 'pdfjs-dist/types/src/display/api';

const getPageText = async (pdf: pdfjsLib.PDFDocumentProxy, pageNo: number) => {
    const page = await pdf.getPage(pageNo);
    const tokenizedText = await page.getTextContent();
    var textItems = tokenizedText.items;
    var finalString = '';
    var line = 0;

    // Concatenate the string of the item to the final string
    for (var i = 0; i < textItems.length; i++) {
        if (line != (textItems[i] as TextItem).transform[5]) {
            if (line != 0) {
                finalString += '\r\n';
            }

            line = (textItems[i] as TextItem).transform[5];
        }
        var item = textItems[i];

        finalString += (item as TextItem).str;
    }
    return finalString;
};

export const getPDFText = async (
    data: string,
    password: string | undefined = undefined
) => {
    const initParams: DocumentInitParameters = {
         data: Buffer.from(data, 'base64'),
        //useSystemFonts: true,
        //disableFontFace: false,
        standardFontDataUrl: 'standard_fonts/'
    };

    if (password !== undefined) {
        initParams.password = password;
    }

    const pdf = await pdfjsLib.getDocument(initParams).promise;
    const maxPages = pdf.numPages;
    const pageTextPromises = [];
    for (let pageNo = 1; pageNo <= maxPages; pageNo += 1) {
        pageTextPromises.push(getPageText(pdf, pageNo));
    }
    const pageTexts = await Promise.all(pageTextPromises);
    const joined = pageTexts.join(' ');
    return joined;
};

使用 pdfjs-dist 3.1.81 版本,这看起来相当不错,但表单字段上的复选框丢失了,文本字段的值显示在每个页面的末尾,而不是保留在上下文中。我觉得这个页面:https://pdftotext.com/基于与我的输出的相似性使用pdfjs,但他们在方框上进行了检查,并且他们的文本字段“答案”是问题。

运行:

import { join } from 'path';
import { readFileSync } from 'fs';

const rawContents = readFileSync(join('directory', 'file.pdf'), 'base64');

const pdfText = await getPDFText(rawContents as string);

有人知道我为什么会丢失支票(盒子就在那里)吗?

我得到的样本:

22. when something something?
☐ 0-3 months ago
☐ 4-6 months ago
☐ 7-12 months ago
☐ 13-18 months ago
☐ 19-24 months ago
☐ 25-60 months ago
☐ I don't know

该网页得到的内容如下:

22. when something something?

✔ 0-3 months ago
☐
☐ 4-6 months ago

☐ 7-12 months ago

☐ 13-18 months ago

☐ 19-24 months ago

☐ 25-60 months ago

☐ I don’t know

再次,我的输出看起来像他们的,但丢失了这些检查。我不确定他们是否使用 pdfjs,但我认为他们确实使用了。

请注意,我已经下载了一些字体并将其放在 standard_fonts 目录中。即使我没有看到警告消息,我是否应该将它们全部复制?

pdf.js pdfjs-dist
2个回答
2
投票

在表单中,复选框是字段边界,不属于任何附近文本的一部分(所有字段都是如此,它们不直接连接到其描述),它们仅具有名称和值。这里放置了 Check Box1 和 Box2,Box3 正在等待表面外观。

特别注意,它们的外观并不固定,它们在展示时会变形,它们是嵌合体,看起来就像存在一样。

在这些 AcroForm 情况下,它们没有本地纯文本等价物,没有任何东西可以检测索引只是指向页面坐标。

PDF.js 是一个 PDF2HTML 转换器,因此可以轻松地将这些索引区域显示为 html 字段。 注意它是一个X

就 PDF 可提取表面而言,没有文本,我们可以看到上面和下面的框只有在这些单选框旁边看到的描述

注意这是一个勾号。除了显示器(查看器)之外没有什么不同

如果我们尝试使用 PDF.js(此处在浏览器中)提取文本,我们只会得到文本

在某些情况下,Symbol 或 ZapfDingbats 原生字体或其他具有这些代码点的 TTF 已被嵌入并适应状态,可能会获得带字体的复选标记符号,但这种情况很少见,除非专门设计。

☐ 如您在案例中看到的那样,然后替换为一个
☑ 正在从字体中选择正确的字体并添加为
☒ 更换不是很容易但可行。

因此,可以使用简单的 pdftotext 或 Python 再次提取通过 HTML 打印为 PDF 的上述符号。

☐ as you see in your case then to replace with one
☑ is picking the correct one from font and add as
☒ replacement it's not very easy but doable.

1
投票

对于其他正在寻找的人:

https://formulae.brew.sh/formula/poppler

这包括

pdftotext
获得复选标记的命令

编辑 经过进一步研究,我绝对喜欢 poppler 的 pdftotext。它确实有一个奇怪之处,即包裹在破折号上的线将被展开减去破折号。我认为它试图变得聪明并假设破折号在那里表示换行。几乎是一个边缘情况,但值得注意。

还有一个节点包装器,可以让您不必处理临时文件:https://www.npmjs.com/package/node-pdftotext

© www.soinside.com 2019 - 2024. All rights reserved.