DEV Community

AsyncMonk
AsyncMonk

Posted on

Page count is the wrong unit for estimating a PDF-to-text job

"How many pages?" is the first question anyone asks about turning a pile of PDFs into text, and it's the number that ends up in the estimate. I spent a day running seven English documents through a PDF extractor and counting, for each, how many places I'd have to touch afterwards. Pages were a poor predictor. One page of a book printed in 1734 needed more fixes than two pages of an arXiv paper, and what kind of fix it was mattered more than how many.

How I counted

A spot is one place I'd have to touch to turn the output into clean running text that matches the page: a wrong, missing or extra word, a line fused with its neighbour or cut into fake table cells, a word broken across a line end, two conflicting versions of one line, or a block in the wrong position. It counts once however many characters it covers. I left page furniture out (running heads, footers, page numbers) because it gets stripped anyway. Four samples are test files I generated myself with invented content, so I know them line by line. For two scanned public-domain books from Internet Archive I transcribed one printed page each and diffed word by word with Python's difflib, which counts a moved phrase twice, once where it went missing and once where it landed. The paper is RAG-Safety-Bench by Adithiyan Rajan Indira Saravanan and Kathleen C. Fraser (arXiv:2609.11758, CC BY 4.0), pages 1–2. Everything went through ImgIng's Extract PDF content with OCR on Auto, and each spot went into one of three buckets: a script can fix it, a person has to look, or editing is the wrong move and the page should be rendered and OCR'd again.

Stacked bar chart of spots to fix per sample, split into script-fixable, needs a person, and re-OCR instead. A2 2, B 6, C 3, D 5, arXiv 43, 1921 book page 41 (10 after re-OCR), 1734 book page 55 (15 after re-OCR)

Blue is cheap

The long bars are mostly blue. The arXiv pages have 42 words broken across a line end (re- / trieve), and on the 1921 page 34 justified lines came out as two Tab-separated cells, as if the paragraph were a table. A short script handles most of it with three rules. It joins a lowercase fragment ending in a hyphen to the lowercase word that opens the next line, and prints every pair it joined so a person can skim the list. On pages I've marked as plain prose, it turns each Tab back into a space. And it puts the space back between a name and a timestamp that got glued to it. On the arXiv pages that meant 40 joins, with two breaks inside the paper's own name left untouched. On the 1921 page it made 4 joins and replaced 34 Tabs. On the weekly report it only had 2 timestamps to fix.

"Most" is carrying weight there. The join rule turned open- / source into opensource, which is wrong, and it left both breaks inside RAG-Safety-Bench alone because a capital follows. That's 3 of 42 that still need eyes, and it's why the script prints what it joined instead of doing it silently. Keeping the Tab rule to prose-only pages matters too: the same Tab rule on the weekly report would flatten its sales table, which the extractor had correctly split into columns. On that report the script only had to put the space back into Leo Park14:09 and Leo Park14:20.

Orange is where the effort goes

Orange spots are few, and each one needs someone who can see the page. On my one-page synthetic scan, the hidden text layer said "24 stores" and the image said "42 stores". The extractor kept both lines, which is the honest thing to do, but only a person can say which is right, and it also placed a recovered line above the heading.

Extract PDF content result for a synthetic scan whose hidden text layer disagrees with the image:

The two-column report had four lines fused with no separator (Finance4. Result), so no regex knows where to cut. The weekly report's bar chart came out as 342 355 372 360 and 310 295 _ _ 180 _: every number is there, and which day it belongs to is gone. One kanban card came back as OPS-416 with no title. The lecture notes lost ŷ entirely and read e = y – .. Each of these is a single spot on the chart, and none of them can be found or fixed without the image open next to the text.

Green means stop editing

The 1734 page is the only green bar. The extractor used the book's embedded tesseract layer, and besides letter errors like Hull and Poiks, 22 spots are words that went missing or moved to another line. You can't repair a sentence whose words are shuffled without the page beside you, and at that point you're retyping. Rendering the page and running OCR on the image took it from 55 spots to 15. It isn't a universal cure: on the 1921 page re-OCR went from 41 spots to 10 only because the Tabs vanished, while its letter-level errors went from 3 to 6.

The furniture I didn't count had its own problems. The lecture notes lost both page numbers, and the weekly report lost all three running headers and all three footers; I don't know why for the report, since my two-column file kept its headers.

What I look at before giving a number

One page of each kind of document in the batch, run through the exact pipeline I'd use, spots sorted into those three buckets. Blue grows with volume but a script absorbs it. Orange grows with volume and needs a person, so it's the column I read first. Green says the pipeline is wrong for that document, and that has to change before counting means anything. Page count can't tell you which of these you're holding: the one-page synthetic scan had only 2 spots, and both were orange. The extractor I used is at https://imging.ai/

Top comments (0)