首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从具有不同结构的表单中提取字段

从具有不同结构的表单中提取字段
EN

Stack Overflow用户
提问于 2017-03-29 02:14:54
回答 2查看 9.3K关注 0票数 12

我正在尝试从资产负债表中提取某些字段。例如,我希望能够指出以下资产负债表的“Inventory”值为1,277,838:

目前,我正在使用Tesseract将图像转换为文本。但是,这种转换会产生文本流,因此很难将字段与它们的值相关联(因为这些值并不总是紧挨着其相应字段的文本)。

经过一些搜索,我读到了Tesseract可以使用uzn文件来读取图像的区域。然而,资产负债表值的特定区域可能会从一种形式转移到另一种形式,所以我对任何可以确定“库存”和1,277,838在同一行上的解决方案感兴趣。理想情况下,我想要一个文本的网格结构输出(这样我就可以在空间上知道哪些文本块在相同的行/列中)。

有人能帮我解释一下我是如何实现这个结果的吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-29 03:25:41

我一直在使用Tesseract和Python (pytesseract库)执行类似的任务。我已经能够使用Tesseract的.hocr输出文件(https://en.wikipedia.org/wiki/HOCR)在页面上找到我的搜索词(例如'Inventory')的位置,然后在页面的一小部分上重新运行Tesseract,从而使该区域的准确率更高。下面是我用来解析来自Tesseract的HOCR输出的代码:

代码语言:javascript
复制
def parse_hocr(search_terms=None, hocr_file=None, regex=None):
    """Parse the hocr file and find a reasonable bounding box for each of the strings
    in search_terms.  Return a dictionary with values as the bounding box to be used for 
    extracting the appropriate text.

    inputs:
        search_terms = Tuple, A tuple of search terms to look for in the HOCR file.

    outputs:
        box_dict = Dictionary, A dictionary whose keys are the elements of search_terms and values
        are the bounding boxes where those terms are located in the document.
    """
    # Make sure the search terms provided are a tuple.
    if not isinstance(search_terms,tuple):
        raise ValueError('The search_terms parameter must be a tuple')

    # Make sure we got a HOCR file handle when called.
    if not hocr_file:
        raise ValueError('The parser must be provided with an HOCR file handle.')

    # Open the hocr file, read it into BeautifulSoup and extract all the ocr words.
    hocr = open(hocr_file,'r').read()
    soup = bs.BeautifulSoup(hocr,'html.parser')
    words = soup.find_all('span',class_='ocrx_word')

    result = dict()

    # Loop through all the words and look for our search terms.        
    for word in words:

        w = word.get_text().lower()

        for s in search_terms:

            # If the word is in our search terms, find the bounding box
            if len(w) > 1 and difflib.SequenceMatcher(None, s, w).ratio() > .5:
                bbox = word['title'].split(';')
                bbox = bbox[0].split(' ')
                bbox = tuple([int(x) for x in bbox[1:]])

                # Update the result dictionary or raise an error if the search term is in there twice.
                if s not in result.keys():
                    result.update({s:bbox})

            else:
                pass

    return result 

这允许我在HOCR文件中搜索适当的术语,并返回该特定单词的边界框。然后,我可以稍微扩展边界框,以便在页面的一个非常小的子集上运行Tesseract。这比仅仅OCRing整个页面的准确性要高得多。显然,其中一些代码是我使用的特定代码,但它应该给您一个开始的地方。

This page对于找到合适的参数提供给Tesseract非常有帮助。我发现页面分割模式对于获得图像小部分的准确结果非常重要。

票数 9
EN

Stack Overflow用户

发布于 2017-03-29 14:58:25

正如gaw89已经提到的,Tesseract可以输出更多的信息,而不仅仅是文本作为流。hocr fileformat还为您提供了每个段落、行、单词的位置(边界框):

代码语言:javascript
复制
$ tesseract 4LV05.png out -l eng hocr

例如,您可以通过以下方法找到单词"Inventory“的边界框

代码语言:javascript
复制
$ grep 'Inventory' out.hocr
 <span class='ocr_line' id='line_1_5' title="bbox 23 183 112 204; baseline 0 -5; x_size 21; x_descenders 5; x_ascenders 4"><span class='ocrx_word' id='word_1_15' title='bbox 23 183 112 204; x_wconf 93'>Inventory</span>

因此,这个单词的边界框垂直地从183到204,对于这个标签的相应值,我们现在必须在相同的垂直空间中搜索框。例如,这可以通过以下方式来实现

代码语言:javascript
复制
$ grep 'bbox [0-9]* 18[0-9]' out.hocr
<p class='ocr_par' id='par_1_4' lang='eng' title="bbox 23 183 112 204">
 <span class='ocr_line' id='line_1_5' title="bbox 23 183 112 204; baseline 0 -5; x_size 21; x_descenders 5; x_ascenders 4"><span class='ocrx_word' id='word_1_15' title='bbox 23 183 112 204; x_wconf 93'>Inventory</span>
 <span class='ocr_line' id='line_1_30' title="bbox 1082 183 1178 202; baseline 0 -3; x_size 22; x_descenders 5.5; x_ascenders 5.5"><span class='ocrx_word' id='word_1_82' title='bbox 1082 183 1178 202; x_wconf 93'>1,277,838</span>
 <span class='ocr_line' id='line_1_54' title="bbox 1301 183 1379 202; baseline 0 -3; x_size 22; x_descenders 5.5; x_ascenders 5.5"><span class='ocrx_word' id='word_1_107' title='bbox 1301 183 1379 202; x_wconf 95'>953,675</span>

第二个结果包含目标值。您可以比较bbox的垂直坐标,以确保提取第一列。

在这个示例中,命令grep就足够了,但当然还有其他方法可以做类似的事情。还要注意,根据页面的倾斜程度,正则表达式可能会被一些其他计算所取代。

或者,您可以尝试使用开放源码的Tabula,它将尝试从pdf中提取表格数据。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43076995

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档