PDF text
The text of a PDF, whole or by page, and the lines holding a word: for search, imports and reading invoices.
Version 1.0.0 · 3 functions · 1 crate
Functions
What use pdf_text.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use pdf_text, pdf_text_pages from pdf_text (Quillo 0.6).
pdf_text(path: str) → stror an errorAll the text of a PDF, pages parted by a blank line. Scanned pages (pictures of text) give nothing: they need OCR.
pdf_text_pages(path: str) → listor an errorThe text of each page, in order: the first item is page 1.
pdf_text_search(path: str, query: str, limit: int) → listor an errorThe lines holding query (in any case), as { page, line, text }, pages and lines counted from 1; at most limit of them (up to 1,000).
Get it
$ quillo install pdf_text # pdf_text.qwer into this folder$ quillo install pdf_text --example # and its example, pdf_text.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/pdf_text.qwer$ curl -O https://quillolang.org/plugins/files/pdf_text.qwe$ curl -O https://quillolang.org/plugins/files/pdf_text_sample.pdfThen, in your program, all of it or only what you call:
use pdf_text.qweruse pdf_text, pdf_text_pages from pdf_text // Quillo 0.6: only theseIt uses this crate, which cargo fetches the first time the plugin is built:
pdf-extract = "0.9"Example
// An invoice's text read from its PDF, page by page, and searched.//// quillo run pdf_text.qwe then open http://localhost:8080/invoiceuse "pdf_text.qwer"let INVOICE = "pdf_text_sample.pdf"route GET /invoice { let pages = pdf_text_pages(INVOICE)? let total = re.find(pages[0], "Total\\s+([\\d.]+)") { pages: len(pages), first_page: pages[0], total: total?.groups[0] }}route GET /text = pdf_text(INVOICE)route GET /search ? { q: str = "due" } = pdf_text_search(INVOICE, q, 20)$ quillo run pdf_text.qwe$ curl 'localhost:8080/invoice'$ curl 'localhost:8080/search?q=due'$ curl 'localhost:8080/text'Source
//! The text of a PDF, whole or page by page, and the lines that hold a word: for search, imports and reading invoices.//! version: 1.0.0//!//! [dependencies]//! pdf-extract = "0.9"use serde_json::{json, Value};const MAX_BYTES: u64 = 100 * 1024 * 1024;// Blank lines at the ends dropped, runs of them kept to one, spaces at line ends trimmed.fn tidy(s: &str) -> String { let mut out: Vec<&str> = vec![]; for line in s.lines().map(str::trim_end) { if line.trim().is_empty() && out.last().map_or(true, |l| l.is_empty()) { continue; } out.push(if line.trim().is_empty() { "" } else { line }); } while out.last() == Some(&"") { out.pop(); } out.join("\n")}fn pages(path: &str) -> Result<Vec<String>, String> { let size = std::fs::metadata(path).map_err(|e| format!("{}: {}", path, e))?.len(); if size > MAX_BYTES { return Err(format!("{}: larger than 100 MB", path)); } // A malformed PDF can make the reader panic: that is an error value here. let p = path.to_string(); let r = std::panic::catch_unwind(move || pdf_extract::extract_text_by_pages(&p)); match r { Ok(Ok(pages)) => Ok(pages.iter().map(|t| tidy(t)).collect()), Ok(Err(e)) => Err(format!("{}: {}", path, e)), Err(_) => Err(format!("{}: the PDF could not be read", path)), }}/// All the text of a PDF, pages parted by a blank line. Scanned pages (pictures of text) give nothing: they need OCR.pub fn pdf_text(path: &str) -> Result<String, String> { Ok(pages(path)?.into_iter().filter(|p| !p.is_empty()).collect::<Vec<_>>().join("\n\n"))}/// The text of each page, in order: the first item is page 1.pub fn pdf_text_pages(path: &str) -> Result<Vec<String>, String> { pages(path)}/// The lines holding `query` (in any case), as `{ page, line, text }`, pages and lines counted from 1; at most `limit` of them (up to 1,000).pub fn pdf_text_search(path: &str, query: &str, limit: i64) -> Result<Vec<Value>, String> { let q = query.to_lowercase(); if q.trim().is_empty() { return Ok(vec![]); } let limit = limit.clamp(1, 1000) as usize; let mut hits = vec![]; for (p, text) in pages(path)?.iter().enumerate() { for (l, line) in text.lines().enumerate() { if line.to_lowercase().contains(&q) { hits.push(json!({ "page": p + 1, "line": l + 1, "text": line.trim() })); if hits.len() >= limit { return Ok(hits); } } } } Ok(hits)}Related
odf_text.qwer · 1.0.0The text of LibreOffice files (.odt, .ods, .odp): paragraphs with headings and lists, sheets as rows of typed cells, slides with their notes, and the title and author.7 views · 9 downloadsPowerPoint text pptx_text.qwer · 1.0.0The text of PowerPoint files: each slide's title, text and speaker notes in slide order, for search and imports.7 views · 7 downloadsWord text docx_text.qwer · 1.0.0The text of Word documents: all of it, paragraph by paragraph with their styles, the tables as rows, and the title and author.7 views · 9 downloadsRTF rtf.qwer · 1.0.0RTF documents read as plain text with their title and author, and simple RTF written: headings, bold and italic runs and tables, for Word, Pages and TextEdit.7 views · 8 downloadsText encodings text_encoding.qwer · 1.0.0Text files in old encodings (Windows-1252, Latin-1, Shift_JIS, GBK, Big5...) detected and read as UTF-8, and written back in them.8 views · 8 downloads7-Zip sevenz.qwer · 1.0.07-Zip archives listed, one file read, opened safely into a folder, and made from a folder.7 views · 8 downloadsThread 0 posts
On PDF text: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.