Как извлечь текст из файлов OneNote на Python

Как извлечь текст из файлов OneNote на Python

Файлы Microsoft OneNote .one являются бинарными документами, которые нельзя читать как обычный текст или разбирать с помощью общих XML‑инструментов. Aspose.Note FOSS for Python предоставляет чисто‑Python парсер, который загружает файлы .one в полную модель объектного документа (DOM), что упрощает программное извлечение текста, метаданных форматирования и гиперссылок.

Преимущества использования Aspose.Note FOSS для Python

  1. Не требуется Microsoft Office: чтение .one файлов на любой платформе, включая серверы Linux CI/CD
  2. Полный доступ к тексту и форматированию: обычный текст, жирный/курсивный/подчёркнутый фрагменты, свойства шрифтов и URL‑адреса гиперссылок
  3. Бесплатно и с открытым исходным кодом: лицензия MIT, отсутствие платы за использование и API‑ключей

Пошаговое руководство

Шаг 1: Установите Aspose.Note FOSS для Python

Установите библиотеку из PyPI. Основной пакет не имеет обязательных зависимостей:

pip install aspose-note

Проверьте установку:

from aspose.note import Document
print("Installation OK")

Шаг 2: Загрузить файл .one

Создайте экземпляр Document, передав путь к файлу:

from aspose.note import Document

doc = Document("MyNotes.one")
print(f"Section: {doc.DisplayName}")
print(f"Pages:   {len(list(doc))}")

Для загрузки из бинарного потока (например, из облачного хранилища или HTTP‑ответа):

from aspose.note import Document

with open("MyNotes.one", "rb") as f:
    doc = Document(f)

Шаг 3: Извлечь весь обычный текст

Используйте GetChildNodes(RichText) для сбора каждого узла RichText в дереве документа. Это выполняет рекурсивный поиск в глубину по всем страницам, структурам и элементам структуры:

from aspose.note import Document, RichText

doc = Document("MyNotes.one")
texts = [rt.Text for rt in doc.GetChildNodes(RichText) if rt.Text]

for text in texts:
    print(text)

Чтобы сохранить весь текст в файл:

from aspose.note import Document, RichText

doc = Document("MyNotes.one")
texts = [rt.Text for rt in doc.GetChildNodes(RichText) if rt.Text]

with open("extracted_text.txt", "w", encoding="utf-8") as out:
    out.write("\n".join(texts))

print(f"Wrote {len(texts)} text blocks to extracted_text.txt")

Шаг 4: Проверка отформатированных фрагментов

Каждый RichText узел содержит TextRuns список TextRun сегментов. Каждый run несет независимый TextStyle с форматированием по символам:

from aspose.note import Document, RichText

doc = Document("MyNotes.one")

for rt in doc.GetChildNodes(RichText):
    for run in rt.TextRuns:
        style = run.Style
        attrs = []
        if style.IsBold:        attrs.append("bold")
        if style.IsItalic:      attrs.append("italic")
        if style.IsUnderline:   attrs.append("underline")
        if style.IsStrikethrough: attrs.append("strikethrough")
        if style.FontName:    attrs.append(f"font={style.FontName}")
        if style.FontSize:    attrs.append(f"size={style.FontSize}pt")
        label = ", ".join(attrs) if attrs else "plain"
        print(f"[{label}] {run.Text!r}")

Шаг 5: Извлечь гиперссылки

Гиперссылки хранятся в отдельных узлах TextRun. Проверьте Style.IsHyperlink и прочитайте Style.HyperlinkAddress:

from aspose.note import Document, RichText

doc = Document("MyNotes.one")

for rt in doc.GetChildNodes(RichText):
    for run in rt.TextRuns:
        if run.Style.IsHyperlink and run.Style.HyperlinkAddress:
            print(f"Link text: {run.Text!r}")
            print(f"URL:       {run.Style.HyperlinkAddress}")

Шаг 6: Извлечение текста по странице

Для извлечения текста, организованного по заголовкам страниц:

from aspose.note import Document, Page, RichText

doc = Document("MyNotes.one")

for page in doc.GetChildNodes(Page):
    title = (
        page.Title.TitleText.Text
        if page.Title and page.Title.TitleText
        else "(untitled)"
    )
    print(f"\n=== {title} ===")
    for rt in page.GetChildNodes(RichText):
        if rt.Text:
            print(rt.Text)

Распространённые проблемы и решения

1. ImportError: Нет модуля с именем ‘aspose’

Cause: Пакет не установлен в активной среде Python.

Исправление:

pip install aspose-note
##Confirm active environment:
pip show aspose-note

2. FileNotFoundError при загрузке файла .one

Причина: Путь к файлу неверен или файл не существует.

Исправление: используйте абсолютный путь или проверьте, существует ли файл перед загрузкой:

from pathlib import Path
from aspose.note import Document

path = Path("MyNotes.one")
if not path.exists():
    raise FileNotFoundError(f"File not found: {path.resolve()}")
doc = Document(str(path))

3. UnicodeEncodeError в Windows при печати

Причина: терминалы Windows могут использовать устаревшую кодировку, которая не может отображать символы Unicode.

Исправление: Перенастройте stdout в начале вашего скрипта:

import sys
if hasattr(sys.stdout, "reconfigure"):
    sys.stdout.reconfigure(encoding="utf-8", errors="replace")

4. Пустой текст приводит к результатам

Cause: Файл .one может быть пустым, содержать только изображения или таблицы (без узлов RichText), либо быть файлом блокнота (.onetoc2), а не файлом раздела (.one).

Fix: Проверьте количество страниц и типы узлов:

from aspose.note import Document

doc = Document("MyNotes.one")
print(f"Pages: {len(list(doc))}")
for page in doc:
    print(f"  Children: {sum(1 for _ in page)}")

5. IncorrectPasswordException

Cause: Файл .one зашифрован. Зашифрованные документы не поддерживаются.

Fix: Aspose.Note FOSS for Python не поддерживает зашифрованные .one файлы. Полнофункциональный коммерческий продукт Aspose.Note поддерживает расшифровку.


Часто задаваемые вопросы

Могу ли я извлечь текст со всех страниц одновременно?

Да. doc.GetChildNodes(RichText) рекурсивно просматривает всё дерево документа, включая все страницы, оглавления и элементы оглавления.

Поддерживает ли библиотека файлы блокнотов .onetoc2?

Нет. Библиотека обрабатывает только файлы разделов .one. Файлы оглавления блокнота (.onetoc2) имеют другой формат и не поддерживаются.

Могу ли я извлекать текст из таблиц?

Да. TableCell узлы содержат RichText дочерние элементы, которые можно прочитать тем же способом:

from aspose.note import Document, Table, TableRow, TableCell, RichText

doc = Document("MyNotes.one")
for table in doc.GetChildNodes(Table):
    for row in table.GetChildNodes(TableRow):
        for cell in row.GetChildNodes(TableCell):
            cell_text = " ".join(rt.Text for rt in cell.GetChildNodes(RichText)).strip()
            print(cell_text, end="\t")
        print()

Какие версии Python поддерживаются?

Python 3.10, 3.11 и 3.12.

Библиотека потокобезопасна?

Каждый экземпляр Document должен использоваться из одного потока. Для параллельного извлечения создайте отдельный Document для каждого потока.


Связанные ресурсы:

 Русский