一、请使用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()
它里面有个错误,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)}]} '''
这个文本块的确是标题,但是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']}")
请将代码中的"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}")
这段代码有个错误,就是
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
好,然后调用:
res = extract_titles_from_pdf(pdf_path, 1.2) print(res) ''' [('赚钱的本质套路一共就3个:底层收智商税、中层找接盘侠、上层', 1), ('玩金融!(完整版)', 1), ('钱就是债!——金融家的秘密,老百姓的盲点!明白这个才能不被', 8), ('收割', 8), ('穷人才想赚快钱!教人致富多为骗局!想变富要明白一个逻辑:分', 11), ('配!', 11), ('历史观比财经观更重要!经济是政治的延伸,而今天是昨日的推', 14), ('演!', 14), ('大钱要靠分配!不是卖苦力赚的!人生是无数个局,看局方能破局', 17), ('为何啥都不好干了?为何经济放缓了?本质在于这一群体快被抽', 21), ('干!', 21), ('过去高增长的本质是什么?', 21), ...] '''
OK 初步完成。