Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ead7b78
Fix(cargo): pined quick-xml version
aragami3070 Mar 12, 2026
1a662bd
Feat(cargo): add calamine crate
aragami3070 Mar 12, 2026
c578c0f
Chore(assets-for-tests): update Book.xlsx
aragami3070 Mar 13, 2026
47ab946
Chore(parsers): add type Bytes for MS office format parsers
aragami3070 Mar 13, 2026
fc62663
Feat(errors): add convert from calamine error to ParserError
aragami3070 Mar 13, 2026
4c81321
Chore(parsers): init xlsx
aragami3070 Mar 13, 2026
ed34930
Feat(parsers): add MSOfficeParser trait
aragami3070 Mar 14, 2026
fa012d8
Feat(pptx): impl MSOfficeParser trait
aragami3070 Mar 14, 2026
4ffec68
Feat(docx): impl MSOfficeParser trait
aragami3070 Mar 14, 2026
49c60bd
Feat(xlsx): init XlsxParser struct
aragami3070 Mar 14, 2026
5ddabcb
Feat(xlsx): add method `new`
aragami3070 Mar 14, 2026
3e75daa
Feat(xlsx): impl MSOfficeParser with get_text method
aragami3070 Mar 14, 2026
adfc791
Fix(parsers): MSOFFIcePaser name typo
aragami3070 Mar 14, 2026
8b8c9e6
Chore(parser): rename all get_text fn names to extract_text
aragami3070 Mar 14, 2026
3ae72be
Feat(errors): add std::fmt error in ParserError
aragami3070 Mar 14, 2026
40a5253
Feat(xlsx): separate and rework extract text from sheets
aragami3070 Mar 14, 2026
fcd57f3
Feat(xlsx): extract images and text from them
aragami3070 Mar 14, 2026
31d0e99
Chore(app): add usage xlsx example
aragami3070 Mar 14, 2026
ead2019
Feat(xlsx): add extract text from xlsx test
aragami3070 Mar 14, 2026
aea6c65
Feat(docs_parser.pyi): update info for python lsp
aragami3070 Mar 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import docs_parser

# NOTE: все эти точно работают и работают хорошо
# (doc_p, _) = docs_parser.get_text("parser/assets/text_and_tables.docx")
# (doc_p, _) = docs_parser.get_text("parser/assets/text_and_tables.docx")
# (doc_p, _) = docs_parser.get_text("parser/assets/some_text.docx")
# (doc_p, _) = docs_parser.get_text("parser/assets/text_tables_png.docx")
# (doc_p, _) = docs_parser.get_text("parser/assets/text_from_img.png")
# (doc_p, _) = docs_parser.get_text("parser/assets/main.typ")
# (doc_p, _) = docs_parser.get_text("parser/assets/main.pdf")
# (doc_p, _) = docs_parser.get_text("parser/assets/too_many_png.docx")
# (doc_p, _) = docs_parser.get_text("parser/assets/Presentation.pptx")
# print(doc_p)
# (doc_p, _) = docs_parser.extract_text("parser/assets/text_and_tables.docx")
# (doc_p, _) = docs_parser.extract_text("parser/assets/text_and_tables.docx")
# (doc_p, _) = docs_parser.extract_text("parser/assets/some_text.docx")
# (doc_p, _) = docs_parser.extract_text("parser/assets/text_tables_png.docx")
# (doc_p, _) = docs_parser.extract_text("parser/assets/text_from_img.png")
# (doc_p, _) = docs_parser.extract_text("parser/assets/main.typ")
# (doc_p, _) = docs_parser.extract_text("parser/assets/main.pdf")
# (doc_p, _) = docs_parser.extract_text("parser/assets/too_many_png.docx")
# (doc_p, _) = docs_parser.extract_text("parser/assets/Presentation.pptx")
(doc_p, _) = docs_parser.extract_text("parser/assets/Book.xlsx")
print(doc_p)
# docs_parser.convert_to_new_format("parser/assets/old_docs.doc", "parser/assets/tests_results")
# docs_parser.convert_to_new_format("parser/assets/old_pres.ppt", "parser/assets/tests_results")
# docs_parser.convert_to_new_format("parser/assets/old_exel.xls", "parser/assets/tests_results")
74 changes: 73 additions & 1 deletion parser/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ mime = "0.3.17"
# NOTE: Для парсинга форматов офиса
docx-rs = "0.4.19"
rustypptx = "0.2.0"
calamine = "0.34.0"
zip = "8.1.0"
quick-xml = "0.39.2"
quick-xml = "0.38.4"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Откатил версию, ибо эти гении перезаписали релиз поменяв апи и у меня один метод упал из-за этого


# NOTE: Для парсинга pdf
pdf-extract = "0.10.0"
Expand Down
Binary file modified parser/assets/Book.xlsx
Binary file not shown.
16 changes: 16 additions & 0 deletions parser/assets/tests_results/extract_text_from_xlsx.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*** Sheet: Лист1 ***/
Имя, Номер
Вася, 1
Петя, 3
Ваня, 2
Тема, 4
Егор, 6
Саша, 5

/*** Sheet: Sheet2 ***/
Страница 2
some text

/************* Image = 0 *************/
МЯУ=191919
/*************************************/
2 changes: 1 addition & 1 deletion parser/docs_parser.pyi
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
def get_text(from_path: str) -> tuple[str, dict[tuple[int, int], bytes]]: ...
def extract_text(from_path: str) -> tuple[str, dict[tuple[int, int], bytes]]: ...
def convert_to_new_format(old_file_path: str, new_path: str): ...
10 changes: 10 additions & 0 deletions parser/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ pub enum ParserError {
#[error("IO error: {0}")]
IoError(#[from] io::Error),

/// Ошибка записи в буффер
#[error("Fmt error: {0}")]
FmtError(#[from] std::fmt::Error),

/// Ошибка парсинга utf-8 из байтов текстового файла
#[error("From utf-8 error: {0}")]
FromUTF8Error(#[from] std::string::FromUtf8Error),
Expand Down Expand Up @@ -61,6 +65,12 @@ pub enum ParserError {
#[error("Docx error: {0}")]
PptxError(#[from] rustypptx::PptxError),

/// Ошибка чтения xlsx
///
/// Ошибки библиотеки calamine для работы с xlsx
#[error("Docx error: {0}")]
XlsxError(#[from] calamine::XlsxError),

/// Ошибка tesseract::InitializeError
#[error("Tesseract init error: {0}")]
TesseractInitError(#[from] tesseract::InitializeError),
Expand Down
6 changes: 3 additions & 3 deletions parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ mod parser {

/// Парсинг текста `from` файла по `path`
#[pyo3::pyfunction]
pub fn get_text(from_path: &str) -> PyResult<(String, ImagesInfo)> {
Ok(crate::match_parsers::get_text(from_path)?)
pub fn extract_text(from_path: &str) -> PyResult<(String, ImagesInfo)> {
Ok(crate::match_parsers::extract_text(from_path)?)
}

/// Конвертер старых Microsoft office форматов в новые
Expand All @@ -34,7 +34,7 @@ mod parser {
/// Функция реализации python модуля, добавляющая в него функции
#[pymodule]
fn docs_parser(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(parser::get_text, m)?)?;
m.add_function(wrap_pyfunction!(parser::extract_text, m)?)?;
m.add_function(wrap_pyfunction!(parser::convert_to_new_format, m)?)?;
Ok(())
}
22 changes: 14 additions & 8 deletions parser/src/match_parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use crate::{
APPLICATION_XLS, APPLICATION_XLSX,
},
errors::ParserError,
parsers::{docx, image::get_from_image, pdf::get_from_pdf, pptx, text::get_from_text},
parsers::{
MSOfficeParser, docx, image::extract_text_from_image, pdf::extract_text_from_pdf, pptx, text::extract_from_text,
xlsx,
},
};

type Result<T> = std::result::Result<T, ParserError>;
Expand All @@ -32,24 +35,27 @@ static INFER: LazyLock<Infer> = LazyLock::new(Infer::new);
/// # Errors
/// - [`ParserError::InvalidFormat`] - тип файла не поддерживается/не определен
/// - Остальные варианты [`ParserError`], если ошибка во время парсинга файла
pub fn get_text(file_name: &str) -> Result<(String, ImagesInfo)> {
pub fn extract_text(file_name: &str) -> Result<(String, ImagesInfo)> {
let file_data = read_data_from_file(file_name)?;
match define_mime_type(&file_data) {
Some(mime)
if mime == APPLICATION_DOCX
|| (mime == APPLICATION_DOCX_ZIP && file_name.ends_with(".docx")) =>
{
let docx_parser = docx::DocxParser::new();
docx_parser.get_from_docx(&file_data)
docx_parser.extract_text(&file_data)
}
Some(mime) if mime == APPLICATION_XLSX => {
let xlsx_parser = xlsx::XlsxParser::new();
xlsx_parser.extract_text(&file_data)
}
Some(mime) if mime == APPLICATION_XLSX => todo!(),
Some(mime) if mime == APPLICATION_PPTX => {
let pptx_parser = pptx::PptxParser::new();
pptx_parser.get_from_pptx(&file_data)
pptx_parser.extract_text(&file_data)
}
Some(mime) if mime == APPLICATION_PDF => Ok((get_from_pdf(&file_data)?, HashMap::new())),
Some(mime) if mime.type_() == TEXT => Ok((get_from_text(&file_data)?, HashMap::new())),
Some(mime) if mime.type_() == IMAGE => Ok((get_from_image(&file_data)?, HashMap::new())),
Some(mime) if mime == APPLICATION_PDF => Ok((extract_text_from_pdf(&file_data)?, HashMap::new())),
Some(mime) if mime.type_() == TEXT => Ok((extract_from_text(&file_data)?, HashMap::new())),
Some(mime) if mime.type_() == IMAGE => Ok((extract_text_from_image(&file_data)?, HashMap::new())),
Some(mime) if is_converted_mime_type(&mime) => Err(ParserError::InvalidFormat(format!(
"Не поддерживается данный тип файла {mime}, но его вы можете конвертировать \
в поддерживаемый формат через отдельный метод конвертации"
Expand Down
Loading
Loading