• ChatGPT 调教指南:从 PDF 提取标题并保存


    一、请使用python编写一段代码,使用pymupdf包从pdf中提取标题,保存标题名称和页数。

    我没有加任何的答案提示,看看 GPT 如何反应。它应该是知道 PDF 没有任何语义信息,一切标题或者正文全是文本框。

    好的,以下是使用pymupdf包从pdf中提取标题,并保存标题名称和页数的代码示例:

    import fitz
    
    def extract_titles(pdf_path):
        doc = fitz.open(pdf_path)
        titles = []
    
        for page in doc:
            blocks = page.get_text("dict")["blocks"]
            
            for block in blocks:
                if block["type"] == 1 and block["bbox"][3] < 100:
                    title = block["text"]
                    page_num = page.number + 1
                    titles.append({"title": title, "page": page_num})
    
        return titles
    
    pdf_path = "example.pdf"
    titles = extract_titles(pdf_path)
    
    for title in titles:
        print("Title:", title["title"])
        print("Page:", title["page"])
        print()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    它里面有个错误,page.getText应该是page.get_text,我改了过来。

    这个逻辑完全不对,我试了以下我手头的一个文字 PDF(三眼文集.pdf),第二页doc[1]的第一行就是标题。看看能不能提取

    pdf_path = r"d:/docs/wealth-books-2023/权谋/三眼文集.pdf"
    doc = fitz.open(pdf_path)
    print(doc[1].get_text("dict")['blocks'][0])
    '''
    {'number': 0,
     'type': 0,
     'bbox': (48.0, 52.383140563964844, 531.0696411132812, 96.42223358154297),
     'lines': [{'spans': [{'size': 16.440000534057617,
         'flags': 4,
         'font': 'MicrosoftYaHeiUI',
         'color': 0,
         'ascender': 1.015625,
         'descender': -0.25439453125,
         'text': '赚钱的本质套路一共就3个:底层收智商税、中层找接盘侠、上层',
         'origin': (48.0, 69.08001708984375),
         'bbox': (48.0,
          52.383140563964844,
          531.0696411132812,
          73.26226043701172)}],
       'wmode': 0,
       'dir': (1.0, 0.0),
       'bbox': (48.0, 52.383140563964844, 531.0696411132812, 73.26226043701172)},
      {'spans': [{'size': 16.440000534057617,
         'flags': 4,
         'font': 'MicrosoftYaHeiUI',
         'color': 0,
         'ascender': 1.015625,
         'descender': -0.25439453125,
         'text': '玩金融!(完整版)',
         'origin': (48.0, 92.239990234375),
         'bbox': (48.0, 75.5431137084961, 199.65902709960938, 96.42223358154297)}],
       'wmode': 0,
       'dir': (1.0, 0.0),
       'bbox': (48.0, 75.5431137084961, 199.65902709960938, 96.42223358154297)}]}
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    这个文本块的确是标题,但是type不是 1,根本提取不出来。

    二、请使用python编写一段代码,使用pymupdf包从pdf中提取标题,保存标题名称和页数,注意不要根据文本块的类型来判断,而是根据其大小。

    但是我们知道,标题的大小明显和正文不一样,比如正文大小是12,标题是16,那OK,我们引导 GPT 从大小方面区分。

    您可以使用以下代码使用pymupdf包从PDF中提取标题和页数,并将其保存在列表中:

    import fitz
    
    def extract_titles(pdf_path):
        doc = fitz.open(pdf_path)
        titles = []
    
        for page_num in range(len(doc)):
            page = doc.load_page(page_num)
            blocks = page.get_text("dict", flags=11)["blocks"]
    
            for block in blocks:
                if block["type"] == 1 and block["bbox"][3] < 100:
                    title = block["text"].strip()
                    titles.append({"title": title, "page": page_num})
    
        return titles
    
    pdf_path = "your_pdf_path.pdf"
    titles = extract_titles(pdf_path)
    
    for title in titles:
        print(f"Title: {title['title']}, Page: {title['page']}")
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    请将代码中的"your_pdf_path.pdf"替换为您要提取标题的PDF路径。该代码使用pymupdf包打开PDF文件并迭代每个页面,然后检查每个文本块的类型和大小。如果文本块的类型为1(即标题)且其边界框高度小于100,将提取标题和页数,并将其添加到标题列表中。最后,打印出所有提取的标题和页数。

    看来还是不改,还是按照文本框高度和类型区分。

    三、请使用python编写一段代码,使用pymupdf包从pdf中提取标题大致方法是获取每一页的每个文本框,如果字体大小超出平均值一定倍数,就判断为标题,之后保存标题名称和页数。

    你可以使用pymupdf包来提取PDF文件中的标题。以下是一个示例代码,根据字体大小判断标题并保存标题名称和页数:

    import fitz
    
    def extract_titles_from_pdf(file_path, threshold=1.5):
        doc = fitz.open(file_path)
        titles = []
    
        for page in doc:
            text_blocks = page.getTextBlocks()
            font_sizes = [block[1] for block in text_blocks]
            avg_font_size = sum(font_sizes) / len(font_sizes)
    
            for block in text_blocks:
                font_size = block[1]
                text = block[4]
    
                if font_size > avg_font_size * threshold:
                    titles.append((text, page.number))
    
        return titles
    
    # 调用示例
    pdf_path = "example.pdf"
    titles = extract_titles_from_pdf(pdf_path)
    for title, page_num in titles:
        print(f"标题: {title}\t页数: {page_num}")
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    这段代码有个错误,就是block的前四个数值是矩形四个分量并不是大小,不过这个思路改一改应该就可以用了。

    四、修改后的代码

    '''
    block: {'number': 1,
      'type': 0,
      'bbox': (158.25, 569.15625, 446.25, 663.375),
      'lines': [{'spans': [{'size': 72.0,
          'flags': 0,
          'font': 'SimSun',
          'color': 16776960,
          'ascender': 1.04296875,
          'descender': -0.265625,
          'text': '三眼文集',
          'origin': (158.25, 644.25),
          'bbox': (158.25, 569.15625, 446.25, 663.375)}],
        'wmode': 0,
        'dir': (1.0, 0.0),
        'bbox': (158.25, 569.15625, 446.25, 663.375)}]}
    '''
    
    
    def extract_titles_from_pdf(file_path, thres=1.2):
        doc = fitz.open(file_path)
        titles = []
    
        for i, page in enumerate(doc):
            blocks = [
                block for block in page.get_text("dict")["blocks"]
                if block['type'] == 0
            ]
            sizes = [
                span['size'] 
                for block in blocks
                for line in block['lines']
                for span in line['spans']
            ]
            avg_size = sum(sizes) / (len(sizes) + 1e-9)
    
            page_titles = [
                (span['text'], i) 
                for block in blocks
                for line in block['lines']
                for span in line['spans']
                if span['size'] > avg_size * thres
            ]
            titles += page_titles
    
        return titles
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    好,然后调用:

    res = extract_titles_from_pdf(pdf_path, 1.2)
    print(res)
    '''
    [('赚钱的本质套路一共就3个:底层收智商税、中层找接盘侠、上层', 1),
     ('玩金融!(完整版)', 1),
     ('钱就是债!——金融家的秘密,老百姓的盲点!明白这个才能不被', 8),
     ('收割', 8),
     ('穷人才想赚快钱!教人致富多为骗局!想变富要明白一个逻辑:分', 11),
     ('配!', 11),
     ('历史观比财经观更重要!经济是政治的延伸,而今天是昨日的推', 14),
     ('演!', 14),
     ('大钱要靠分配!不是卖苦力赚的!人生是无数个局,看局方能破局', 17),
     ('为何啥都不好干了?为何经济放缓了?本质在于这一群体快被抽', 21),
     ('干!', 21),
     ('过去高增长的本质是什么?', 21),
     ...]
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    OK 初步完成。

  • 相关阅读:
    Linux 提权-MySQL UDF
    搭建Spring的源码环境
    消失的遗传力的进一步剖分及应用
    Spring框架在Bean中的管理(第十课)
    JVM —— 运行时数据区域
    【NodeJs-5天学习】第三天实战篇① ——10行代码给她造个熬夜提醒睡觉机器人
    3516DV300 推流
    Docker 网络与资源控制
    【TVM源码学习笔记】3.1.3 工作空间更新
    力扣学习笔记——49. 字母异位词分组
  • 原文地址:https://blog.csdn.net/wizardforcel/article/details/133465513