magic-pdf 0.5.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- magic_pdf/__init__.py +0 -0
- magic_pdf/cli/__init__.py +0 -0
- magic_pdf/cli/magicpdf.py +294 -0
- magic_pdf/dict2md/__init__.py +0 -0
- magic_pdf/dict2md/mkcontent.py +397 -0
- magic_pdf/dict2md/ocr_mkcontent.py +356 -0
- magic_pdf/filter/__init__.py +0 -0
- magic_pdf/filter/pdf_classify_by_type.py +381 -0
- magic_pdf/filter/pdf_meta_scan.py +368 -0
- magic_pdf/layout/__init__.py +0 -0
- magic_pdf/layout/bbox_sort.py +681 -0
- magic_pdf/layout/layout_det_utils.py +182 -0
- magic_pdf/layout/layout_sort.py +732 -0
- magic_pdf/layout/layout_spiler_recog.py +101 -0
- magic_pdf/layout/mcol_sort.py +336 -0
- magic_pdf/libs/Constants.py +11 -0
- magic_pdf/libs/MakeContentConfig.py +10 -0
- magic_pdf/libs/ModelBlockTypeEnum.py +9 -0
- magic_pdf/libs/__init__.py +0 -0
- magic_pdf/libs/boxbase.py +408 -0
- magic_pdf/libs/calc_span_stats.py +239 -0
- magic_pdf/libs/commons.py +204 -0
- magic_pdf/libs/config_reader.py +63 -0
- magic_pdf/libs/convert_utils.py +5 -0
- magic_pdf/libs/coordinate_transform.py +9 -0
- magic_pdf/libs/detect_language_from_model.py +21 -0
- magic_pdf/libs/draw_bbox.py +227 -0
- magic_pdf/libs/drop_reason.py +27 -0
- magic_pdf/libs/drop_tag.py +19 -0
- magic_pdf/libs/hash_utils.py +15 -0
- magic_pdf/libs/json_compressor.py +27 -0
- magic_pdf/libs/language.py +31 -0
- magic_pdf/libs/markdown_utils.py +31 -0
- magic_pdf/libs/math.py +9 -0
- magic_pdf/libs/nlp_utils.py +203 -0
- magic_pdf/libs/ocr_content_type.py +21 -0
- magic_pdf/libs/path_utils.py +23 -0
- magic_pdf/libs/pdf_image_tools.py +33 -0
- magic_pdf/libs/safe_filename.py +11 -0
- magic_pdf/libs/textbase.py +33 -0
- magic_pdf/libs/version.py +1 -0
- magic_pdf/libs/vis_utils.py +308 -0
- magic_pdf/model/__init__.py +0 -0
- magic_pdf/model/doc_analyze_by_360layout.py +8 -0
- magic_pdf/model/doc_analyze_by_pp_structurev2.py +125 -0
- magic_pdf/model/magic_model.py +632 -0
- magic_pdf/para/__init__.py +0 -0
- magic_pdf/para/block_continuation_processor.py +562 -0
- magic_pdf/para/block_termination_processor.py +480 -0
- magic_pdf/para/commons.py +222 -0
- magic_pdf/para/denoise.py +246 -0
- magic_pdf/para/draw.py +121 -0
- magic_pdf/para/exceptions.py +198 -0
- magic_pdf/para/layout_match_processor.py +40 -0
- magic_pdf/para/para_pipeline.py +297 -0
- magic_pdf/para/para_split.py +644 -0
- magic_pdf/para/para_split_v2.py +772 -0
- magic_pdf/para/raw_processor.py +207 -0
- magic_pdf/para/stats.py +268 -0
- magic_pdf/para/title_processor.py +1014 -0
- magic_pdf/pdf_parse_by_ocr.py +219 -0
- magic_pdf/pdf_parse_by_ocr_v2.py +17 -0
- magic_pdf/pdf_parse_by_txt.py +410 -0
- magic_pdf/pdf_parse_by_txt_v2.py +56 -0
- magic_pdf/pdf_parse_for_train.py +685 -0
- magic_pdf/pdf_parse_union_core.py +241 -0
- magic_pdf/pipe/AbsPipe.py +112 -0
- magic_pdf/pipe/OCRPipe.py +28 -0
- magic_pdf/pipe/TXTPipe.py +29 -0
- magic_pdf/pipe/UNIPipe.py +83 -0
- magic_pdf/pipe/__init__.py +0 -0
- magic_pdf/post_proc/__init__.py +0 -0
- magic_pdf/post_proc/detect_para.py +3472 -0
- magic_pdf/post_proc/pdf_post_filter.py +67 -0
- magic_pdf/post_proc/remove_footnote.py +153 -0
- magic_pdf/pre_proc/__init__.py +0 -0
- magic_pdf/pre_proc/citationmarker_remove.py +157 -0
- magic_pdf/pre_proc/construct_page_dict.py +72 -0
- magic_pdf/pre_proc/cut_image.py +71 -0
- magic_pdf/pre_proc/detect_equation.py +134 -0
- magic_pdf/pre_proc/detect_footer_by_model.py +64 -0
- magic_pdf/pre_proc/detect_footer_header_by_statistics.py +284 -0
- magic_pdf/pre_proc/detect_footnote.py +170 -0
- magic_pdf/pre_proc/detect_header.py +64 -0
- magic_pdf/pre_proc/detect_images.py +647 -0
- magic_pdf/pre_proc/detect_page_number.py +64 -0
- magic_pdf/pre_proc/detect_tables.py +62 -0
- magic_pdf/pre_proc/equations_replace.py +559 -0
- magic_pdf/pre_proc/fix_image.py +244 -0
- magic_pdf/pre_proc/fix_table.py +270 -0
- magic_pdf/pre_proc/main_text_font.py +23 -0
- magic_pdf/pre_proc/ocr_detect_all_bboxes.py +115 -0
- magic_pdf/pre_proc/ocr_detect_layout.py +133 -0
- magic_pdf/pre_proc/ocr_dict_merge.py +336 -0
- magic_pdf/pre_proc/ocr_span_list_modify.py +258 -0
- magic_pdf/pre_proc/pdf_pre_filter.py +74 -0
- magic_pdf/pre_proc/post_layout_split.py +0 -0
- magic_pdf/pre_proc/remove_bbox_overlap.py +98 -0
- magic_pdf/pre_proc/remove_colored_strip_bbox.py +79 -0
- magic_pdf/pre_proc/remove_footer_header.py +117 -0
- magic_pdf/pre_proc/remove_rotate_bbox.py +188 -0
- magic_pdf/pre_proc/resolve_bbox_conflict.py +191 -0
- magic_pdf/pre_proc/solve_line_alien.py +29 -0
- magic_pdf/pre_proc/statistics.py +12 -0
- magic_pdf/rw/AbsReaderWriter.py +34 -0
- magic_pdf/rw/DiskReaderWriter.py +66 -0
- magic_pdf/rw/S3ReaderWriter.py +107 -0
- magic_pdf/rw/__init__.py +0 -0
- magic_pdf/spark/__init__.py +0 -0
- magic_pdf/spark/spark_api.py +51 -0
- magic_pdf/train_utils/__init__.py +0 -0
- magic_pdf/train_utils/convert_to_train_format.py +65 -0
- magic_pdf/train_utils/extract_caption.py +59 -0
- magic_pdf/train_utils/remove_footer_header.py +159 -0
- magic_pdf/train_utils/vis_utils.py +327 -0
- magic_pdf/user_api.py +136 -0
- magic_pdf-0.5.4.dist-info/LICENSE.md +661 -0
- magic_pdf-0.5.4.dist-info/METADATA +24 -0
- magic_pdf-0.5.4.dist-info/RECORD +121 -0
- magic_pdf-0.5.4.dist-info/WHEEL +5 -0
- magic_pdf-0.5.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,368 @@
|
|
1
|
+
"""
|
2
|
+
输入: s3路径,每行一个
|
3
|
+
输出: pdf文件元信息,包括每一页上的所有图片的长宽高,bbox位置
|
4
|
+
"""
|
5
|
+
import sys
|
6
|
+
import click
|
7
|
+
|
8
|
+
from magic_pdf.libs.commons import read_file, mymax, get_top_percent_list
|
9
|
+
from magic_pdf.libs.commons import fitz
|
10
|
+
from loguru import logger
|
11
|
+
from collections import Counter
|
12
|
+
|
13
|
+
from magic_pdf.libs.drop_reason import DropReason
|
14
|
+
from magic_pdf.libs.language import detect_lang
|
15
|
+
|
16
|
+
scan_max_page = 50
|
17
|
+
junk_limit_min = 10
|
18
|
+
|
19
|
+
|
20
|
+
def calculate_max_image_area_per_page(result:list, page_width_pts, page_height_pts):
|
21
|
+
max_image_area_per_page = [mymax([(x1 - x0) * (y1 - y0) for x0, y0, x1, y1, _ in page_img_sz]) for page_img_sz in
|
22
|
+
result]
|
23
|
+
page_area = int(page_width_pts) * int(page_height_pts)
|
24
|
+
max_image_area_per_page = [area / page_area for area in max_image_area_per_page]
|
25
|
+
max_image_area_per_page = [area for area in max_image_area_per_page if area > 0.6]
|
26
|
+
return max_image_area_per_page
|
27
|
+
|
28
|
+
def process_image(page, junk_img_bojids=[]):
|
29
|
+
page_result = []# 存每个页面里的多张图四元组信息
|
30
|
+
items = page.get_images()
|
31
|
+
dedup = set()
|
32
|
+
for img in items:
|
33
|
+
# 这里返回的是图片在page上的实际展示的大小。返回一个数组,每个元素第一部分是
|
34
|
+
img_bojid = img[0]# 在pdf文件中是全局唯一的,如果这个图反复出现在pdf里那么就可能是垃圾信息,例如水印、页眉页脚等
|
35
|
+
if img_bojid in junk_img_bojids:# 如果是垃圾图像,就跳过
|
36
|
+
continue
|
37
|
+
recs = page.get_image_rects(img, transform=True)
|
38
|
+
if recs:
|
39
|
+
rec = recs[0][0]
|
40
|
+
x0, y0, x1, y1 = map(int, rec)
|
41
|
+
width = x1 - x0
|
42
|
+
height = y1 - y0
|
43
|
+
if (x0, y0, x1, y1, img_bojid) in dedup: # 这里面会出现一些重复的bbox,无需重复出现,需要去掉
|
44
|
+
continue
|
45
|
+
if not all([width, height]): # 长和宽任何一个都不能是0,否则这个图片不可见,没有实际意义
|
46
|
+
continue
|
47
|
+
dedup.add((x0, y0, x1, y1, img_bojid))
|
48
|
+
page_result.append([x0, y0, x1, y1, img_bojid])
|
49
|
+
return page_result
|
50
|
+
def get_image_info(doc: fitz.Document, page_width_pts, page_height_pts) -> list:
|
51
|
+
"""
|
52
|
+
返回每个页面里的图片的四元组,每个页面多个图片。
|
53
|
+
:param doc:
|
54
|
+
:return:
|
55
|
+
"""
|
56
|
+
# 使用 Counter 计数 img_bojid 的出现次数
|
57
|
+
img_bojid_counter = Counter(img[0] for page in doc for img in page.get_images())
|
58
|
+
# 找出出现次数超过 len(doc) 半数的 img_bojid
|
59
|
+
|
60
|
+
junk_limit = max(len(doc)*0.5, junk_limit_min)# 对一些页数比较少的进行豁免
|
61
|
+
|
62
|
+
junk_img_bojids = [img_bojid for img_bojid, count in img_bojid_counter.items() if count >= junk_limit]
|
63
|
+
|
64
|
+
#todo 加个判断,用前十页就行,这些垃圾图片需要满足两个条件,不止出现的次数要足够多,而且图片占书页面积的比例要足够大,且图与图大小都差不多
|
65
|
+
#有两种扫描版,一种文字版,这里可能会有误判
|
66
|
+
#扫描版1:每页都有所有扫描页图片,特点是图占比大,每页展示1张
|
67
|
+
#扫描版2,每页存储的扫描页图片数量递增,特点是图占比大,每页展示1张,需要清空junklist跑前50页图片信息用于分类判断
|
68
|
+
#文字版1.每页存储所有图片,特点是图片占页面比例不大,每页展示可能为0也可能不止1张 这种pdf需要拿前10页抽样检测img大小和个数,如果符合需要清空junklist
|
69
|
+
imgs_len_list = [len(page.get_images()) for page in doc]
|
70
|
+
|
71
|
+
special_limit_pages = 10
|
72
|
+
|
73
|
+
# 统一用前十页结果做判断
|
74
|
+
result = []
|
75
|
+
break_loop = False
|
76
|
+
for i, page in enumerate(doc):
|
77
|
+
if break_loop:
|
78
|
+
break
|
79
|
+
if i >= special_limit_pages:
|
80
|
+
break
|
81
|
+
page_result = process_image(page) # 这里不传junk_img_bojids,拿前十页所有图片信息用于后续分析
|
82
|
+
result.append(page_result)
|
83
|
+
for item in result:
|
84
|
+
if not any(item): # 如果任何一页没有图片,说明是个文字版,需要判断是否为特殊文字版
|
85
|
+
if max(imgs_len_list) == min(imgs_len_list) and max(imgs_len_list) >= junk_limit_min:# 如果是特殊文字版,就把junklist置空并break
|
86
|
+
junk_img_bojids = []
|
87
|
+
else:# 不是特殊文字版,是个普通文字版,但是存在垃圾图片,不置空junklist
|
88
|
+
pass
|
89
|
+
break_loop = True
|
90
|
+
break
|
91
|
+
if not break_loop:
|
92
|
+
# 获取前80%的元素
|
93
|
+
top_eighty_percent = get_top_percent_list(imgs_len_list, 0.8)
|
94
|
+
# 检查前80%的元素是否都相等
|
95
|
+
if len(set(top_eighty_percent)) == 1 and max(imgs_len_list) >= junk_limit_min:
|
96
|
+
|
97
|
+
# # 如果前10页跑完都有图,根据每页图片数量是否相等判断是否需要清除junklist
|
98
|
+
# if max(imgs_len_list) == min(imgs_len_list) and max(imgs_len_list) >= junk_limit_min:
|
99
|
+
|
100
|
+
#前10页都有图,且每页数量一致,需要检测图片大小占页面的比例判断是否需要清除junklist
|
101
|
+
max_image_area_per_page = calculate_max_image_area_per_page(result, page_width_pts, page_height_pts)
|
102
|
+
if len(max_image_area_per_page) < 0.8 * special_limit_pages: # 前10页不全是大图,说明可能是个文字版pdf,把垃圾图片list置空
|
103
|
+
junk_img_bojids = []
|
104
|
+
else:# 前10页都有图,而且80%都是大图,且每页图片数量一致并都很多,说明是扫描版1,不需要清空junklist
|
105
|
+
pass
|
106
|
+
else:# 每页图片数量不一致,需要清掉junklist全量跑前50页图片
|
107
|
+
junk_img_bojids = []
|
108
|
+
|
109
|
+
#正式进入取前50页图片的信息流程
|
110
|
+
result = []
|
111
|
+
for i, page in enumerate(doc):
|
112
|
+
if i >= scan_max_page:
|
113
|
+
break
|
114
|
+
page_result = process_image(page, junk_img_bojids)
|
115
|
+
# logger.info(f"page {i} img_len: {len(page_result)}")
|
116
|
+
result.append(page_result)
|
117
|
+
|
118
|
+
return result, junk_img_bojids
|
119
|
+
|
120
|
+
|
121
|
+
def get_pdf_page_size_pts(doc: fitz.Document):
|
122
|
+
page_cnt = len(doc)
|
123
|
+
l: int = min(page_cnt, 50)
|
124
|
+
#把所有宽度和高度塞到两个list 分别取中位数(中间遇到了个在纵页里塞横页的pdf,导致宽高互换了)
|
125
|
+
page_width_list = []
|
126
|
+
page_height_list = []
|
127
|
+
for i in range(l):
|
128
|
+
page = doc[i]
|
129
|
+
page_rect = page.rect
|
130
|
+
page_width_list.append(page_rect.width)
|
131
|
+
page_height_list.append(page_rect.height)
|
132
|
+
|
133
|
+
page_width_list.sort()
|
134
|
+
page_height_list.sort()
|
135
|
+
|
136
|
+
median_width = page_width_list[len(page_width_list) // 2]
|
137
|
+
median_height = page_height_list[len(page_height_list) // 2]
|
138
|
+
|
139
|
+
|
140
|
+
return median_width, median_height
|
141
|
+
|
142
|
+
|
143
|
+
def get_pdf_textlen_per_page(doc: fitz.Document):
|
144
|
+
text_len_lst = []
|
145
|
+
for page in doc:
|
146
|
+
# 拿包含img和text的所有blocks
|
147
|
+
# text_block = page.get_text("blocks")
|
148
|
+
# 拿所有text的blocks
|
149
|
+
# text_block = page.get_text("words")
|
150
|
+
# text_block_len = sum([len(t[4]) for t in text_block])
|
151
|
+
#拿所有text的str
|
152
|
+
text_block = page.get_text("text")
|
153
|
+
text_block_len = len(text_block)
|
154
|
+
# logger.info(f"page {page.number} text_block_len: {text_block_len}")
|
155
|
+
text_len_lst.append(text_block_len)
|
156
|
+
|
157
|
+
return text_len_lst
|
158
|
+
|
159
|
+
def get_pdf_text_layout_per_page(doc: fitz.Document):
|
160
|
+
"""
|
161
|
+
根据PDF文档的每一页文本布局,判断该页的文本布局是横向、纵向还是未知。
|
162
|
+
|
163
|
+
Args:
|
164
|
+
doc (fitz.Document): PDF文档对象。
|
165
|
+
|
166
|
+
Returns:
|
167
|
+
List[str]: 每一页的文本布局(横向、纵向、未知)。
|
168
|
+
|
169
|
+
"""
|
170
|
+
text_layout_list = []
|
171
|
+
|
172
|
+
for page_id, page in enumerate(doc):
|
173
|
+
if page_id >= scan_max_page:
|
174
|
+
break
|
175
|
+
# 创建每一页的纵向和横向的文本行数计数器
|
176
|
+
vertical_count = 0
|
177
|
+
horizontal_count = 0
|
178
|
+
text_dict = page.get_text("dict")
|
179
|
+
if "blocks" in text_dict:
|
180
|
+
for block in text_dict["blocks"]:
|
181
|
+
if 'lines' in block:
|
182
|
+
for line in block["lines"]:
|
183
|
+
# 获取line的bbox顶点坐标
|
184
|
+
x0, y0, x1, y1 = line['bbox']
|
185
|
+
# 计算bbox的宽高
|
186
|
+
width = x1 - x0
|
187
|
+
height = y1 - y0
|
188
|
+
# 计算bbox的面积
|
189
|
+
area = width * height
|
190
|
+
font_sizes = []
|
191
|
+
for span in line['spans']:
|
192
|
+
if 'size' in span:
|
193
|
+
font_sizes.append(span['size'])
|
194
|
+
if len(font_sizes) > 0:
|
195
|
+
average_font_size = sum(font_sizes) / len(font_sizes)
|
196
|
+
else:
|
197
|
+
average_font_size = 10 # 有的line拿不到font_size,先定一个阈值100
|
198
|
+
if area <= average_font_size ** 2: # 判断bbox的面积是否小于平均字体大小的平方,单字无法计算是横向还是纵向
|
199
|
+
continue
|
200
|
+
else:
|
201
|
+
if 'wmode' in line: # 通过wmode判断文本方向
|
202
|
+
if line['wmode'] == 1: # 判断是否为竖向文本
|
203
|
+
vertical_count += 1
|
204
|
+
elif line['wmode'] == 0: # 判断是否为横向文本
|
205
|
+
horizontal_count += 1
|
206
|
+
# if 'dir' in line: # 通过旋转角度计算判断文本方向
|
207
|
+
# # 获取行的 "dir" 值
|
208
|
+
# dir_value = line['dir']
|
209
|
+
# cosine, sine = dir_value
|
210
|
+
# # 计算角度
|
211
|
+
# angle = math.degrees(math.acos(cosine))
|
212
|
+
#
|
213
|
+
# # 判断是否为横向文本
|
214
|
+
# if abs(angle - 0) < 0.01 or abs(angle - 180) < 0.01:
|
215
|
+
# # line_text = ' '.join(span['text'] for span in line['spans'])
|
216
|
+
# # print('This line is horizontal:', line_text)
|
217
|
+
# horizontal_count += 1
|
218
|
+
# # 判断是否为纵向文本
|
219
|
+
# elif abs(angle - 90) < 0.01 or abs(angle - 270) < 0.01:
|
220
|
+
# # line_text = ' '.join(span['text'] for span in line['spans'])
|
221
|
+
# # print('This line is vertical:', line_text)
|
222
|
+
# vertical_count += 1
|
223
|
+
# print(f"page_id: {page_id}, vertical_count: {vertical_count}, horizontal_count: {horizontal_count}")
|
224
|
+
# 判断每一页的文本布局
|
225
|
+
if vertical_count == 0 and horizontal_count == 0: # 该页没有文本,无法判断
|
226
|
+
text_layout_list.append("unknow")
|
227
|
+
continue
|
228
|
+
else:
|
229
|
+
if vertical_count > horizontal_count: # 该页的文本纵向行数大于横向的
|
230
|
+
text_layout_list.append("vertical")
|
231
|
+
else: # 该页的文本横向行数大于纵向的
|
232
|
+
text_layout_list.append("horizontal")
|
233
|
+
# logger.info(f"page_id: {page_id}, vertical_count: {vertical_count}, horizontal_count: {horizontal_count}")
|
234
|
+
return text_layout_list
|
235
|
+
|
236
|
+
'''定义一个自定义异常用来抛出单页svg太多的pdf'''
|
237
|
+
class PageSvgsTooManyError(Exception):
|
238
|
+
def __init__(self, message="Page SVGs are too many"):
|
239
|
+
self.message = message
|
240
|
+
super().__init__(self.message)
|
241
|
+
def get_svgs_per_page(doc: fitz.Document):
|
242
|
+
svgs_len_list = []
|
243
|
+
for page_id, page in enumerate(doc):
|
244
|
+
# svgs = page.get_drawings()
|
245
|
+
svgs = page.get_cdrawings() # 切换成get_cdrawings,效率更高
|
246
|
+
len_svgs = len(svgs)
|
247
|
+
if len_svgs >= 3000:
|
248
|
+
raise PageSvgsTooManyError()
|
249
|
+
else:
|
250
|
+
svgs_len_list.append(len_svgs)
|
251
|
+
# logger.info(f"page_id: {page_id}, svgs_len: {len(svgs)}")
|
252
|
+
return svgs_len_list
|
253
|
+
|
254
|
+
def get_imgs_per_page(doc: fitz.Document):
|
255
|
+
imgs_len_list = []
|
256
|
+
for page_id, page in enumerate(doc):
|
257
|
+
imgs = page.get_images()
|
258
|
+
imgs_len_list.append(len(imgs))
|
259
|
+
# logger.info(f"page_id: {page}, imgs_len: {len(imgs)}")
|
260
|
+
|
261
|
+
return imgs_len_list
|
262
|
+
|
263
|
+
|
264
|
+
def get_language(doc: fitz.Document):
|
265
|
+
"""
|
266
|
+
获取PDF文档的语言。
|
267
|
+
Args:
|
268
|
+
doc (fitz.Document): PDF文档对象。
|
269
|
+
Returns:
|
270
|
+
str: 文档语言,如 "en-US"。
|
271
|
+
"""
|
272
|
+
language_lst = []
|
273
|
+
for page_id, page in enumerate(doc):
|
274
|
+
if page_id >= scan_max_page:
|
275
|
+
break
|
276
|
+
# 拿所有text的str
|
277
|
+
text_block = page.get_text("text")
|
278
|
+
page_language = detect_lang(text_block)
|
279
|
+
language_lst.append(page_language)
|
280
|
+
|
281
|
+
# logger.info(f"page_id: {page_id}, page_language: {page_language}")
|
282
|
+
|
283
|
+
# 统计text_language_list中每种语言的个数
|
284
|
+
count_dict = Counter(language_lst)
|
285
|
+
# 输出text_language_list中出现的次数最多的语言
|
286
|
+
language = max(count_dict, key=count_dict.get)
|
287
|
+
return language
|
288
|
+
|
289
|
+
|
290
|
+
def pdf_meta_scan(pdf_bytes: bytes):
|
291
|
+
"""
|
292
|
+
:param s3_pdf_path:
|
293
|
+
:param pdf_bytes: pdf文件的二进制数据
|
294
|
+
几个维度来评价:是否加密,是否需要密码,纸张大小,总页数,是否文字可提取
|
295
|
+
"""
|
296
|
+
doc = fitz.open("pdf", pdf_bytes)
|
297
|
+
is_needs_password = doc.needs_pass
|
298
|
+
is_encrypted = doc.is_encrypted
|
299
|
+
total_page = len(doc)
|
300
|
+
if total_page == 0:
|
301
|
+
logger.warning(f"drop this pdf, drop_reason: {DropReason.EMPTY_PDF}")
|
302
|
+
result = {"_need_drop": True, "_drop_reason": DropReason.EMPTY_PDF}
|
303
|
+
return result
|
304
|
+
else:
|
305
|
+
page_width_pts, page_height_pts = get_pdf_page_size_pts(doc)
|
306
|
+
# logger.info(f"page_width_pts: {page_width_pts}, page_height_pts: {page_height_pts}")
|
307
|
+
|
308
|
+
# svgs_per_page = get_svgs_per_page(doc)
|
309
|
+
# logger.info(f"svgs_per_page: {svgs_per_page}")
|
310
|
+
imgs_per_page = get_imgs_per_page(doc)
|
311
|
+
# logger.info(f"imgs_per_page: {imgs_per_page}")
|
312
|
+
|
313
|
+
image_info_per_page, junk_img_bojids = get_image_info(doc, page_width_pts, page_height_pts)
|
314
|
+
# logger.info(f"image_info_per_page: {image_info_per_page}, junk_img_bojids: {junk_img_bojids}")
|
315
|
+
text_len_per_page = get_pdf_textlen_per_page(doc)
|
316
|
+
# logger.info(f"text_len_per_page: {text_len_per_page}")
|
317
|
+
text_layout_per_page = get_pdf_text_layout_per_page(doc)
|
318
|
+
# logger.info(f"text_layout_per_page: {text_layout_per_page}")
|
319
|
+
text_language = get_language(doc)
|
320
|
+
# logger.info(f"text_language: {text_language}")
|
321
|
+
|
322
|
+
|
323
|
+
# 最后输出一条json
|
324
|
+
res = {
|
325
|
+
"is_needs_password": is_needs_password,
|
326
|
+
"is_encrypted": is_encrypted,
|
327
|
+
"total_page": total_page,
|
328
|
+
"page_width_pts": int(page_width_pts),
|
329
|
+
"page_height_pts": int(page_height_pts),
|
330
|
+
"image_info_per_page": image_info_per_page,
|
331
|
+
"text_len_per_page": text_len_per_page,
|
332
|
+
"text_layout_per_page": text_layout_per_page,
|
333
|
+
"text_language": text_language,
|
334
|
+
# "svgs_per_page": svgs_per_page,
|
335
|
+
"imgs_per_page": imgs_per_page, # 增加每页img数量list
|
336
|
+
"junk_img_bojids": junk_img_bojids, # 增加垃圾图片的bojid list
|
337
|
+
"metadata": doc.metadata
|
338
|
+
}
|
339
|
+
# logger.info(json.dumps(res, ensure_ascii=False))
|
340
|
+
return res
|
341
|
+
|
342
|
+
|
343
|
+
@click.command()
|
344
|
+
@click.option('--s3-pdf-path', help='s3上pdf文件的路径')
|
345
|
+
@click.option('--s3-profile', help='s3上的profile')
|
346
|
+
def main(s3_pdf_path: str, s3_profile: str):
|
347
|
+
"""
|
348
|
+
|
349
|
+
"""
|
350
|
+
try:
|
351
|
+
file_content = read_file(s3_pdf_path, s3_profile)
|
352
|
+
pdf_meta_scan(file_content)
|
353
|
+
except Exception as e:
|
354
|
+
print(f"ERROR: {s3_pdf_path}, {e}", file=sys.stderr)
|
355
|
+
logger.exception(e)
|
356
|
+
|
357
|
+
|
358
|
+
if __name__ == '__main__':
|
359
|
+
main()
|
360
|
+
# "D:\project/20231108code-clean\pdf_cost_time\竖排例子\净空法师-大乘无量寿.pdf"
|
361
|
+
# "D:\project/20231108code-clean\pdf_cost_time\竖排例子\三国演义_繁体竖排版.pdf"
|
362
|
+
# "D:\project/20231108code-clean\pdf_cost_time\scihub\scihub_86800000\libgen.scimag86880000-86880999.zip_10.1021/acsami.1c03109.s002.pdf"
|
363
|
+
# "D:/project/20231108code-clean/pdf_cost_time/scihub/scihub_18600000/libgen.scimag18645000-18645999.zip_10.1021/om3006239.pdf"
|
364
|
+
# file_content = read_file("D:/project/20231108code-clean/pdf_cost_time/scihub/scihub_31000000/libgen.scimag31098000-31098999.zip_10.1109/isit.2006.261791.pdf","")
|
365
|
+
# file_content = read_file("D:\project/20231108code-clean\pdf_cost_time\竖排例子\净空法师_大乘无量寿.pdf","")
|
366
|
+
# doc = fitz.open("pdf", file_content)
|
367
|
+
# text_layout_lst = get_pdf_text_layout_per_page(doc)
|
368
|
+
# print(text_layout_lst)
|
File without changes
|