pdftext 0.3.2__tar.gz → 0.3.4__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pdftext
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Extract structured text from pdfs quickly
5
5
  Home-page: https://github.com/VikParuchuri/pdftext
6
6
  License: Apache-2.0
@@ -64,6 +64,7 @@ pdftext PDF_PATH --out_path output.txt --json
64
64
  - `--json` specifies json output
65
65
  - `--sort` will attempt to sort in reading order if specified.
66
66
  - `--pages` will specify pages (comma separated) to extract
67
+ - `--keep_chars` will keep individual characters in the json output
67
68
 
68
69
  The output will be a json list, with each item in the list corresponding to a single page in the input pdf (in order). Each page will include the following keys:
69
70
 
@@ -107,7 +108,7 @@ import pypdfium2 as pdfium
107
108
  from pdftext.extraction import dictionary_output
108
109
 
109
110
  pdf = pdfium.PdfDocument(PDF_PATH)
110
- text = dictionary_output(pdf, sort=False, page_range=[1,2,3]) # Optional arguments explained above
111
+ text = dictionary_output(pdf, sort=False, page_range=[1,2,3], keep_chars=False) # Optional arguments explained above
111
112
  ```
112
113
 
113
114
  If you want more customization, check out the `pdftext.extraction._get_pages` function for a starting point to dig deeper. pdftext is a pretty thin wrapper around [pypdfium2](https://pypdfium2.readthedocs.io/en/stable/), so you might want to look at the documentation for that as well.
@@ -41,6 +41,7 @@ pdftext PDF_PATH --out_path output.txt --json
41
41
  - `--json` specifies json output
42
42
  - `--sort` will attempt to sort in reading order if specified.
43
43
  - `--pages` will specify pages (comma separated) to extract
44
+ - `--keep_chars` will keep individual characters in the json output
44
45
 
45
46
  The output will be a json list, with each item in the list corresponding to a single page in the input pdf (in order). Each page will include the following keys:
46
47
 
@@ -84,7 +85,7 @@ import pypdfium2 as pdfium
84
85
  from pdftext.extraction import dictionary_output
85
86
 
86
87
  pdf = pdfium.PdfDocument(PDF_PATH)
87
- text = dictionary_output(pdf, sort=False, page_range=[1,2,3]) # Optional arguments explained above
88
+ text = dictionary_output(pdf, sort=False, page_range=[1,2,3], keep_chars=False) # Optional arguments explained above
88
89
  ```
89
90
 
90
91
  If you want more customization, check out the `pdftext.extraction._get_pages` function for a starting point to dig deeper. pdftext is a pretty thin wrapper around [pypdfium2](https://pypdfium2.readthedocs.io/en/stable/), so you might want to look at the documentation for that as well.
@@ -13,6 +13,7 @@ def main():
13
13
  parser.add_argument("--sort", action="store_true", help="Attempt to sort the text by reading order", default=False)
14
14
  parser.add_argument("--keep_hyphens", action="store_true", help="Keep hyphens in words", default=False)
15
15
  parser.add_argument("--pages", type=str, help="Comma separated pages to extract, like 1,2,3", default=None)
16
+ parser.add_argument("--keep_chars", action="store_true", help="Keep character level information", default=False)
16
17
  args = parser.parse_args()
17
18
 
18
19
  pdf_doc = pdfium.PdfDocument(args.pdf_path)
@@ -22,7 +23,7 @@ def main():
22
23
  assert all(p <= len(pdf_doc) for p in pages), "Invalid page number(s) provided"
23
24
 
24
25
  if args.json:
25
- text = dictionary_output(pdf_doc, sort=args.sort, page_range=pages)
26
+ text = dictionary_output(pdf_doc, sort=args.sort, page_range=pages, keep_chars=args.keep_chars)
26
27
  text = json.dumps(text)
27
28
  else:
28
29
  text = plain_text_output(pdf_doc, sort=args.sort, hyphens=args.keep_hyphens, page_range=pages)
@@ -28,7 +28,7 @@ def paginated_plain_text_output(pdf_doc, sort=False, model=None, hyphens=False,
28
28
  return text
29
29
 
30
30
 
31
- def dictionary_output(pdf_doc, sort=False, model=None, page_range=None):
31
+ def dictionary_output(pdf_doc, sort=False, model=None, page_range=None, keep_chars=False):
32
32
  pages = _get_pages(pdf_doc, model, page_range)
33
33
  for page in pages:
34
34
  for block in page["blocks"]:
@@ -44,6 +44,12 @@ def dictionary_output(pdf_doc, sort=False, model=None, page_range=None):
44
44
  span["text"] = postprocess_text(span["text"])
45
45
  span["text"] = handle_hyphens(span["text"], keep_hyphens=True)
46
46
 
47
+ if not keep_chars:
48
+ del span["chars"]
49
+ else:
50
+ for char in span["chars"]:
51
+ char["bbox"] = unnormalize_bbox(char["bbox"], page["width"], page["height"])
52
+
47
53
  line["bbox"] = unnormalize_bbox(line["bbox"], page["width"], page["height"])
48
54
  block["bbox"] = unnormalize_bbox(block["bbox"], page["width"], page["height"])
49
55
  if sort:
@@ -81,7 +81,11 @@ def update_span(line, span):
81
81
  span["char_start_idx"] = span["chars"][0]["char_idx"]
82
82
  span["char_end_idx"] = span["chars"][-1]["char_idx"]
83
83
 
84
- del span["chars"]
84
+ # Remove unneeded keys from the characters
85
+ for char in span["chars"]:
86
+ del_keys = [k for k in list(char.keys()) if k not in ["char", "bbox"]]
87
+ for key in del_keys:
88
+ del char[key]
85
89
  line["spans"].append(span)
86
90
  span = {"chars": []}
87
91
  return span
@@ -129,7 +133,7 @@ def infer_single_page(text_chars, block_threshold=settings.BLOCK_THRESHOLD):
129
133
  span = update_span(line, span)
130
134
  line = update_line(block, line)
131
135
  block = update_block(blocks, block)
132
- elif prev_char["char"] in LINE_BREAKS and prediction_probs[1] >= .5: # Look for newline character as a forcing signal for a new line
136
+ elif prev_char["char"] in LINE_BREAKS: # Look for newline character as a forcing signal for a new line
133
137
  span = update_span(line, span)
134
138
  line = update_line(block, line)
135
139
  elif prev_font_info != font_info:
@@ -37,13 +37,12 @@ def unnormalize_bbox(bbox, page_width, page_height):
37
37
 
38
38
 
39
39
  def get_fontname(textpage, char_index):
40
- n_bytes = settings.FONT_BUFFER_SIZE
40
+ n_bytes = pdfium_c.FPDFText_GetFontInfo(textpage, char_index, None, 0, None)
41
41
  buffer = ctypes.create_string_buffer(n_bytes)
42
42
  # Re-interpret the type from char to unsigned short as required by the function
43
43
  buffer_ptr = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_ushort))
44
44
  flag_buffer = ctypes.c_int()
45
- flag_ptr = ctypes.pointer(flag_buffer)
46
- font_info = pdfium_c.FPDFText_GetFontInfo(textpage, char_index, buffer_ptr, n_bytes, flag_ptr)
45
+ font_info = pdfium_c.FPDFText_GetFontInfo(textpage, char_index, buffer_ptr, n_bytes, flag_buffer)
47
46
  if font_info == 0:
48
47
  return None, None
49
48
  try:
@@ -62,13 +61,11 @@ def page_to_device(page, x, y, page_width, page_height, page_rotation: int):
62
61
  page_rotation = 3
63
62
  else:
64
63
  page_rotation = 0
65
- device_x = ctypes.c_int()
66
- device_y = ctypes.c_int()
67
- device_x_ptr = ctypes.pointer(device_x)
68
- device_y_ptr = ctypes.pointer(device_y)
69
64
  width = math.ceil(page_width)
70
65
  height = math.ceil(page_height)
71
- pdfium_c.FPDF_PageToDevice(page, 0, 0, width, height, page_rotation, x, y, device_x_ptr, device_y_ptr)
66
+ device_x = ctypes.c_int()
67
+ device_y = ctypes.c_int()
68
+ pdfium_c.FPDF_PageToDevice(page, 0, 0, width, height, page_rotation, x, y, device_x, device_y)
72
69
  x = device_x.value
73
70
  y = device_y.value
74
71
  return x, y
@@ -135,4 +132,4 @@ def rotate_page_bbox(bbox, angle_deg, width, height):
135
132
  bbox = rotate_page_bbox(bbox, 90, width, height)
136
133
  bbox = rotate_page_bbox(bbox, 180, width, height)
137
134
 
138
- return bbox
135
+ return bbox
@@ -8,7 +8,6 @@ class Settings(BaseSettings):
8
8
  MODEL_PATH: str = os.path.join(BASE_PATH, "models", "dt.joblib")
9
9
 
10
10
  # Fonts
11
- FONT_BUFFER_SIZE: int = 1024 # How many characters to buffer when reading a font name
12
11
  FONTNAME_SAMPLE_FREQ: int = 10
13
12
 
14
13
  # Inference
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pdftext"
3
- version = "0.3.2"
3
+ version = "0.3.4"
4
4
  description = "Extract structured text from pdfs quickly"
5
5
  authors = ["Vik Paruchuri <vik.paruchuri@gmail.com>"]
6
6
  license = "Apache-2.0"
File without changes
File without changes
File without changes
File without changes