Commit Graph

25 Commits

Author SHA1 Message Date
Jeremy Singer-Vine 474f74c906 Add another test for use_text_flow 2023-07-01 18:41:58 -04:00
Jeremy Singer-Vine 4b373977be Add .extract_text_lines & related .search params
Inspired by https://github.com/jsvine/pdfplumber/discussions/852,
it turns out that .search(...) gets us most of the way, already.

Added a few params (`main_group`, `return_groups`, `return_chars`) to
.search(...) to enable this, which also make that method more generally
flexible.
2023-04-13 08:13:16 -04:00
Jeremy Singer-Vine ebb93eae15 Simplify char_begins_new_word
Calculating the bounding boxes of the words is, upon reflection and
testing, not necessary. Instead, all we need is the latest character in
the current word.
2023-04-13 08:13:16 -04:00
Jeremy Singer-Vine 8368954eaa Handle whitespace-only and empty search results
With regular expressions, patterns made up entirely of optional groups
(e.g., r"(dfsdgfwerw)?") can return match objects that are, effectively,
empty. These were being treated as real search results, and throwing
errors in the process. Now they're being treated as non-results.

Separately but relatedly, whitespace-only searches were throwing errors.
This was due to (a) how PDFs generally represent whitespace (implicitly,
rather than explicit space characters), and (b) how pdfplumber
internally represents those spaces while performing layout analysis.
This caused search results to have no explicit bounding box, throwing
errors. Now, similarly to handling empty search results, we handle
all-whitespace search results by considering them to be non-results.
2023-04-13 08:13:16 -04:00
Jeremy Singer-Vine d3662dec06 Mimic text layout better by padding right/bottom
Adds `layout_width` and `layout_height` to `utils.extract_text`, set to
page width and height by default on `page.extract_text`.
2023-02-13 17:38:40 -05:00
Jeremy Singer-Vine 3424b57612 Refactor text-extraction utilities 2023-02-07 17:06:59 -05:00
Jeremy Singer-Vine 1e976568d9 Reallow non-callable key_fn in .cluster_objects()
Resolves https://github.com/jsvine/pdfplumber/issues/691

Thanks to @jfuruness for flagging.
2022-10-01 09:35:42 -04:00
Jeremy Singer-Vine 35fd4298bc Add test_extract_text_punctuation 2022-07-17 12:51:07 -04:00
Shannon Shen 5193c26c31 Consider punctuation when extracting words (#682)
Adds an optional argument to the `extract_words` function that allows to enforce breaking tokens at punctuation. PR by @lolipopshock.
2022-07-16 09:58:10 -04:00
Jeremy Singer-Vine ad3df11954 Fix .extract_text(layout=True) for text-less pages
Fixes https://github.com/jsvine/pdfplumber/issues/658

Thanks to @ethanscorey for flagging!
2022-05-27 14:41:57 -04:00
Jeremy Singer-Vine 58b1ab1b0a Add (experimental) page.search(...) feature
First proposed here: https://github.com/jsvine/pdfplumber/issues/201

Adding this feature involved refactoring and re-engineering a good chunk
of the text-layout-extraction code. As part of that, this commit
introduces two new classes, in utils.py: LayoutEngine and TextLayout.
They should be considered provisional, and may change name/approach in
the future.
2022-05-13 16:04:03 -04:00
Jeremy Singer-Vine 9587cc7d22 Add type annotations and refactor accordingly
A fairly large commit, adding type annotations/hints to the entire
library, and refactoring the library accordingly.

Most of the refactoring changes should have no practical effect on
usage, but several others are notable:

- Added `TableSettings` class, a behind-the-scenes handler for managing
  and validating table-extraction settings.
- Renamed the positional argument to `.to_csv(...)` and `.to_json(...)`
  from `types` to `object_types`.
- Tweaked the output of `.to_json(...)` so that, if an object type is
  not present for a given page, it has no key in the page's object
  representation.
- Removed `utils.filter_objects(...)` and move the functionality to
  within the `FilteredPage.objects` property calculation, the only part
  of the library that used it.
- Removed code that sets `pdfminer.pdftypes.STRICT = True` and
  `pdfminer.pdfinterp.STRICT = True`, since that [has now been the
  default for a
  while](https://github.com/pdfminer/pdfminer.six/commit/9439a3a31a347836aad1c1226168156125d9505f).
2022-05-06 09:43:50 -04:00
Jeremy Singer-Vine d72b879665 Enforce import order via isort 2021-12-16 22:22:54 -05:00
Jeremy Singer-Vine d235d4bbc4 Add experimental .extract_text(layout=True)
See the docstring in utils.words_to_layout for details on the
implementation.

Addresses issue #10 and related issues.
2021-11-02 23:12:17 -04:00
Jeremy Singer-Vine 87b947f8f6 Remove decimalizing (but let CLI adjust precision)
Per discussion at https://github.com/jsvine/pdfplumber/discussions/346
and input from @ramcdona, this commit changes pdfplumber's behavior
regarding floating point numbers. Specifically, it removes all
conversion of floats to Decimal objects. This brings several advantages:

- Increased precision (where applicable)
- Decreased code complexity
- Increased performance (~10% speedup on test suite)
- Increased fidelity to `pdfminer.six` output

These seem to outweigh the disadvantages:

- Some tests break (but have been easily fixed) due to increased
  precision and/or floating point arithmetic artifacts
- Some users' scripts may also break, if they depend on strict equality
  testing, though these *should* also be easily fixable

Because some form of automatic rounding may still be desirable for the
pdfplumber CLI utility, the conversion methods (.to_csv, .to_json) have
been adjusted to accept a `precision` argument.
2021-10-19 21:51:33 -04:00
Jeremy Singer-Vine b4b0282730 Make tests flake8-compatible 2020-12-16 22:29:51 -05:00
Jeremy Singer-Vine 5c62be2e16 Format all tests with psf/black 2020-12-16 22:19:17 -05:00
Jeremy Singer-Vine d6309a9b47 Add "direction" attribute to extracted words
"direction" == 1 when upright words go LTR and non-upright words go TTB,
and -1 when the opposite is true. This attribute should help in reusing
the results of `.extract_words` in other functions, so that the user
knows how the extracted word corresponds to the word's layout on the
page.
2020-08-30 22:30:14 -04:00
Jeremy Singer-Vine 84f91811df Rework .extract_words and add use_text_flow param
Taking @samkit-jain's smart question about sort-order into account, this
commit reworks `.extract_words`, making the sorting more explicit, and
adding an option to *not* sort, via `use_text_flow=True`, which follows
the original PDF's text flow, rather than presorting all characters top-down,
left-right.

To do so required rethinking the word-delineation logic,
which in turn motivated a shift toward a more object-oriented approach
(especially to keep track of settings without passing them from function
to function). Now `.extract_text`'s logic is encapsulated in a new class,
`TextExtractor`.
2020-08-30 18:36:03 -04:00
Jeremy Singer-Vine c8b200ee7c Refactor .extract_words and allow attrib-grouping
This commit refactors and hopefully makes clearer the logic in
utils.extract_words. It also adds a new parameter, `extra_attrs`, which
allows the user to pass a list of attributes on which to group all
characters.

For instance, passing `extra_attrs=["fontname", "size"]` will not allow
characters with different font names or sizes to become part of the same
word. As a benefit, those resulting word dicts will contain `"fontname"`
and `"size"` attributes — providing a long-requested feature (cf. issue
2020-08-29 16:05:31 -04:00
Jeremy Singer-Vine a5e7d7fa52 Remove pandas from dev requirements and tests
Results in needing one more # pragma: nocover statement, but on a
simple line of code. See PR #253 for details and motivation.
2020-08-15 12:03:34 -04:00
Jeremy Singer-Vine 047ad345b4 Add relative param to .crop & err on invalid boxes
Addresses https://github.com/jsvine/pdfplumber/issues/245

Also adds `relative` param to .within_bbox, and adds a new
utils.calculate_area(bbox) method.
2020-08-13 22:25:58 -04:00
Jeremy Singer-Vine cbc91c67d0 Add convert.py/.to_json/.to_csv & improve testcov
Moves most of the logic previously in cli.py to convert.py, for usage by
other submodules. Adds Container.to_json and Container.to_csv. Makes
adjustments/fixes to other parts of the library, based on edge-cases
encountered (such as infinite recursion in anntations).
2020-08-13 08:37:46 -04:00
Jeremy Singer-Vine 8320d6479d Change .move_to_avg to .snap_objects & mv to utils
Also: Simplify the function, and make it based on the attribute you want
to snap *to*, not just the axis/orientation across which to snap.
2020-08-05 22:52:36 -04:00
Jeremy Singer-Vine d16aa13ca2 Fix utils.extract_words & .resize_object, + tests
- Fixes `.extract_words`, which had been returning incorrect results when `horizontal_ltr = False`
- Fixes `.resize_object`, which had been failing in various permutations
- Brings utils.py test coverage to 100%
2020-08-01 12:27:07 -04:00