Camelot在

问题描述

我正在尝试使用Camelot解析PDF中的表格。单元格中包含多行文本,有些则用空行分隔文本的各个部分:

First line
Second line

Third line

我希望将其解析为First line\nSecond line\n\nThird line(注意双行中断),但是我得到的却是:T\nFirst line\nSecond line\nhird line。两次换行符后的第一个字符移到文本的开头,而我只得到一个换行符。

我也尝试过使用表格,但是当表格中有一个空行时,它会弄乱整个表格(实际上是数据帧),并且在有些单词的情况下,它会在字符之间放置一个空格。

编辑:

我的主要问题是删除多个换行符。如果我知道空行在哪里,可以从代码中修复另一个

解决方法

我的朋友,你可以在这里查看示例

https://camelot-py.readthedocs.io/en/master/user/advanced.html#improve-guessed-table-rows

表格= camelot.read_pdf('group_rows.pdf',flavour ='stream',row_tol = 10)

表[0] .df

我用下面的代码解决了同样的问题

tables = camelot.read_pdf(file,flavor ='stream',table_areas = ['24,618,579,93'],column = ['67,315,369,483,571'],row_tol = 10,strip_text ='t \ r \ n \ v' )

,

在双行中断的情况下,我也遇到了相同的问题。在您的情况下,这就是切换字符。我花了一些时间查看代码,并做了一些更改并解决了该问题。您可以使用以下代码。 添加以下代码后,不要使用camelot.read_pdf,而是使用我制作的自定义方法read_pdf_custom() 为了获得更好的体验,我建议您使用camelot v == 0.8.2

import sys
import warnings
from camelot import read_pdf
from camelot import handlers
from camelot.core import TableList
from camelot.parsers import Lattice
from camelot.parsers.base import BaseParser
from camelot.core import Table
import camelot
from camelot.utils import validate_input,remove_extra,TemporaryDirectory,get_page_layout,get_text_objects,get_rotation,is_url,download_url,scale_image,scale_pdf,segments_in_bbox,text_in_bbox,merge_close_lines,get_table_index,compute_accuracy,compute_whitespace

    
    
from camelot.image_processing import (
    adaptive_threshold,find_lines,find_contours,find_joints,)

class custom_lattice(Lattice):
    def _generate_columns_and_rows(self,table_idx,tk):
        # select elements which lie within table_bbox
        t_bbox = {}
        v_s,h_s = segments_in_bbox(
            tk,self.vertical_segments,self.horizontal_segments
        )
        custom_horizontal_indexes=[]
        custom_vertical_indexes=[]
        for zzz in self.horizontal_text:
            try:
                h_extracted_text=self.find_between(str(zzz),"'","'").strip()
                h_text_index=self.find_between(str(zzz),"LTTextLineHorizontal","'").strip().split(",")
                custom_horizontal_indexes.append(h_text_index[1])
            except:
                pass



        inserted=0
        for xxx in self.vertical_text:
            v_extracted_text=self.find_between(str(xxx),"'").strip()
            v_text_index=self.find_between(str(xxx),"LTTextLineVertical",")
            custom_vertical_indexes.append(v_text_index[1])
            vertical_second_index=v_text_index[1]
            try:
                horizontal_index=custom_horizontal_indexes.index(vertical_second_index)
                self.horizontal_text.insert(horizontal_index,xxx)
            except Exception as exxx:
                pass
        self.vertical_text=[]
        t_bbox["horizontal"] = text_in_bbox(tk,self.horizontal_text)
        t_bbox["vertical"] = text_in_bbox(tk,self.vertical_text)

        t_bbox["horizontal"].sort(key=lambda x: (-x.y0,x.x0))
        t_bbox["vertical"].sort(key=lambda x: (x.x0,-x.y0))

        self.t_bbox = t_bbox

        cols,rows = zip(*self.table_bbox[tk])
        cols,rows = list(cols),list(rows)
        cols.extend([tk[0],tk[2]])
        rows.extend([tk[1],tk[3]])
        cols = merge_close_lines(sorted(cols),line_tol=self.line_tol)
        rows = merge_close_lines(sorted(rows,reverse=True),line_tol=self.line_tol)
        cols = [(cols[i],cols[i + 1]) for i in range(0,len(cols) - 1)]
        rows = [(rows[i],rows[i + 1]) for i in range(0,len(rows) - 1)]

        return cols,rows,v_s,h_s
    
    
    def _generate_table(self,cols,**kwargs):
        print("\n")
        v_s = kwargs.get("v_s")
        h_s = kwargs.get("h_s")
        if v_s is None or h_s is None:
            raise ValueError("No segments found on {}".format(self.rootname))

        table = Table(cols,rows)
        table = table.set_edges(v_s,h_s,joint_tol=self.joint_tol)
        table = table.set_border()
        table = table.set_span()


        pos_errors = []
        for direction in ["vertical","horizontal"]:
            for t in self.t_bbox[direction]:
                indices,error = get_table_index(
                    table,t,direction,split_text=self.split_text,flag_size=self.flag_size,strip_text=self.strip_text,)
                if indices[:2] != (-1,-1):
                    pos_errors.append(error)
                    indices = Lattice._reduce_index(
                        table,indices,shift_text=self.shift_text
                    )
                    for r_idx,c_idx,text in indices:
                        temp_text=text.strip().replace("\n","")
                        if len(temp_text)==1:
                            text=temp_text

                        table.cells[r_idx][c_idx].text = text
        accuracy = compute_accuracy([[100,pos_errors]])
        if self.copy_text is not None:
            table = Lattice._copy_spanning_text(table,copy_text=self.copy_text)

        data = table.data
        table.df = pd.DataFrame(data)
        table.shape = table.df.shape

        whitespace = compute_whitespace(data)
        table.flavor = "lattice"
        table.accuracy = accuracy
        table.whitespace = whitespace
        table.order = table_idx + 1
        table.page = int(os.path.basename(self.rootname).replace("page-",""))

        # for plotting
        _text = []
        _text.extend([(t.x0,t.y0,t.x1,t.y1) for t in self.horizontal_text])
        _text.extend([(t.x0,t.y1) for t in self.vertical_text])
        table._text = _text
        table._image = (self.image,self.table_bbox_unscaled)
        table._segments = (self.vertical_segments,self.horizontal_segments)
        table._textedges = None

        return table
        
class PDFHandler(handlers.PDFHandler):
    def parse(
        self,flavor="lattice",suppress_stdout=False,layout_kwargs={},**kwargs
    ):

        tables = []
        with TemporaryDirectory() as tempdir:
            for p in self.pages:
                self._save_page(self.filepath,p,tempdir)
            pages = [
                os.path.join(tempdir,f"page-{p}.pdf") for p in self.pages
            ]
            parser = custom_lattice(**kwargs) if flavor == "lattice" else Stream(**kwargs)
            for p in pages:
                t = parser.extract_tables(
                    p,suppress_stdout=suppress_stdout,layout_kwargs=layout_kwargs
                )
                tables.extend(t)
        return TableList(sorted(tables))

    

def read_pdf_custom(
    filepath,pages="1",password=None,**kwargs
):

    if flavor not in ["lattice","stream"]:
        raise NotImplementedError(
            "Unknown flavor specified." " Use either 'lattice' or 'stream'"
        )

    with warnings.catch_warnings():
        if suppress_stdout:
            warnings.simplefilter("ignore")

        validate_input(kwargs,flavor=flavor)
        p = PDFHandler(filepath,pages=pages,password=password)
        kwargs = remove_extra(kwargs,flavor=flavor)
        tables = p.parse(
            flavor=flavor,layout_kwargs=layout_kwargs,**kwargs
        )
        return tables

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...