【python】基于深度学习的中英文文献PDF中参考文献提取

一、灵感

在看中英文文献的时候,有时候想要这篇文献的参考文献的情况,作为人类,很容易知道一遍文章的参考文献位于什么位置,每一条参考文献的具体内容。然而对于计算机来说,提取高质量的PDF内容并非易事。

其一,仅通过文字识别OCR的方式很难准确高质量的提取参考文献的,参考博客:【python实战】获取英文文献pdf中参考文献信息 - 简书

其二,不同的文献的布局方式不同,有的单栏,有的双栏,通过OCR方式提取的参考文献可能在这篇文献有效,而在另外一篇文献中可能就无法有效提取。

二、解决办法

既然通过传统方法行不通,那就采用人工智能的方法进行pdf的识别。

文本采用端到端的PDF解析工具MinerU:https://github.com/opendatalab/MinerU/blob/master/README_zh-CN.md

  • 布局检测:使用LayoutLMv3模型进行区域检测,如图像表格,标题,文本等;
  • 公式检测:使用YOLOv8进行公式检测,包含行内公式行间公式
  • 公式识别:使用UniMERNet进行公式识别;
  • 表格识别:使用StructEqTable进行表格识别;
  • 光学字符识别:使用PaddleOCR进行文本识别;

根据说明配置好Magic-PDF,有N卡的建议根据说明开启CUDA加速,开和不开提取时间差别蛮大的 ,命令行输入:

magic-pdf pdf-command --pdf "1.pdf" --inside_model true

1.pdf为我的pdf文件名,根据自己的进行修改,开启GPU加速后1分钟左右即可出结果,此时会自动生成一个文件夹:

打开layout.pdf ,可以看到文献的布局被正确识别,而且能够自动删去页眉页脚。

无论中英文文献、单栏还是双栏都能够被正确提取。 

Magic-PDF还有包括公式提取等功能,有兴趣的可以自行探索,本文用于提取参考文献内容,打开提取结果中的.md文件:

可以看到参考文献部分的布局、内容都是正确的,这是通过OCR方式很难做到的,接下来就是写一个函数从md中获取参考文献部分的内容了,主要思路如下:

  • 读取文件:首先,函数读取指定文件路径的内容,并将其按行存储为一个列表 markdown_text

  • 定义关键词:函数定义了三个关键词列表:

    • start_keywords: 包含可能标识参考文献部分开始的关键词,如 "References"、"参考文献" 等。
    • end_keywords: 包含可能标识参考文献部分结束的关键词,如 "Notes"、"附录" 等。
    • content_keywords: 包含可能标识目录部分的关键词,如 "目录"、"CONTENTS" 等。
  • 查找参考文献的起始位置

    • 首先检查文件中是否存在与 content_keywords 相关的目录关键词,如果存在,则从目录部分后的第50行开始查找参考文献的开始位置。
    • 如果找到了 content_keywords 中的目录关键词,则继续从该位置开始查找 start_keywords 中的关键词,以确定参考文献部分的开始。
    • 如果没有找到目录关键词或结论关键词,则直接在整个文本中查找 start_keywords 以确定参考文献部分的开始。
  • 查找参考文献的结束位置

    • 从确定的开始位置继续查找,直到找到 end_keywords 中的某个关键词,来确定参考文献部分的结束位置。
    • 如果没有找到结束关键词,则参考文献部分的结束位置被设置为文本的末尾。
  • 提取并清理参考文献内容

    • 提取从开始位置到结束位置之间的文本内容。
    • 对每一行内容进行清理,删除多余的空格,保留英文或数字字符之间的空格。
  • 过滤参考文献内容

    • 仅保留以 [ 或数字开头的行,这些行通常是参考文献的具体条目。
    • 最后将过滤后的内容返回。

 完整代码如下:

 def extract_references_content(self, file_path):
        """
        提取参考文献内容。
        """
        with open(file_path, 'r', encoding='utf-8') as file:
            markdown_text = file.readlines()

        start_keywords = ['References', 'REFERENCES', 'referenCes', '参考文献', 'R EFERENCES']
        end_keywords = ['Notes', '附录', '致谢', '注释', 'APPENDIX']
        content_keywords = ['目录', 'CONTENTS', 'C ONTENTS']
        start_pos = None
        end_pos = None

        # 检查目录或CONTENTS等关键词
        for idx, line in enumerate(markdown_text):
            if any(keyword in line for keyword in content_keywords):
                start_pos = min(idx + 50, len(markdown_text))
                break

        # 如果检查到了目录关键词,从目录后的第50行开始查找结论关键词
        if start_pos is not None:
            for idx in range(start_pos, len(markdown_text)):
                if any(keyword in markdown_text[idx] for keyword in start_keywords):
                    start_pos = idx + 1
                    break

        # 如果没有找到目录关键词或结论关键词,则查找参考文献关键词
        if start_pos is None:
            for idx, line in enumerate(markdown_text):
                if any(keyword in line for keyword in start_keywords):
                    start_pos = idx + 1
                    break

        # 查找结束关键词
        if start_pos is not None:
            for idx in range(start_pos, len(markdown_text)):
                if any(keyword in markdown_text[idx] for keyword in end_keywords):
                    end_pos = idx
                    break
            if end_pos is None:
                end_pos = len(markdown_text)

            references_content = ''.join(markdown_text[start_pos:end_pos]).strip()
        else:
            references_content = ""

        def clean_line(line):
            line = line.lstrip()
            new_line = []
            for i in range(len(line)):
                if line[i] == ' ':
                    if (i > 0 and i < len(line) - 1 and
                            re.match(r'[a-zA-Z0-9]', line[i - 1]) and
                            re.match(r'[a-zA-Z0-9]', line[i + 1])):
                        new_line.append(' ')
                    else:
                        continue
                else:
                    new_line.append(line[i])
            return ''.join(new_line)

        references_content = '\n'.join(clean_line(line) for line in references_content.split('\n'))

        filtered_lines = []
        for line in references_content.split('\n'):
            if line.startswith('[') or (line and line[0].isdigit()):
                filtered_lines.append(line)
        references_content = '\n'.join(filtered_lines)
        return references_content

要使用Python提取英文文献的表格,你可以使用一些库和工具来帮助你完成这个任务。以下是一种可能的方法: 1. 使用Python的 requests 库下载文献:首先,你需要从网络上获得英文文献的原始数据。你可以使用 requests 库发送HTTP请求,并获取文献的内容。 ```python import requests url = "https://example.com/your_paper.pdf" # 替换为你的文献链接 response = requests.get(url) pdf_content = response.content ``` 2. 使用 Python 的 PyPDF2 库解析 PDF:如果你的英文文献是以 PDF 格式提供的,你可以使用 PyPDF2 库来解析PDF文件,并提取的表格。 ```python import PyPDF2 pdf = PyPDF2.PdfFileReader(pdf_content) num_pages = pdf.getNumPages() tables = [] for page_num in range(num_pages): page = pdf.getPage(page_num) table = page.extract_tables() # 提取当前页面的所有表格 tables.extend(table) # 将当前页面的表格添加到表格列表 ``` 3. 使用 Python 的 pandas 库处理表格数据:一旦你提取出表格,你可以使用 pandas 库来处理和分析表格数据。 ```python import pandas as pd df = pd.DataFrame(tables[0][1:], columns=tables[0][0]) # 假设提取的第一个表格是感兴趣的表格,将其转换为DataFrame # 进一步处理表格数据,例如筛选特定的列或行 filtered_df = df[['Column1', 'Column2']] # 替换为你感兴趣的列名 ``` 请注意,这只是一种可能的方法,并且需要根据具体情况进行适当的修改。此外,实际的表格提取可能会遇到一些挑战,例如表格结构复杂、文献排版不一致等。因此,在处理文献的表格时,你可能需要根据具体情况进行更多的自定义和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值