Мы рады объявить о выпуске GroupDocs.Parser for Python v26.10, доступном с ноября 2026. Этот выпуск обновляет базовый движок до версии 26.8 и переходит с .NET Core 3.1 на .NET 10.0.14, устраняя две уязвимости типа отказ в обслуживании в System.Security.Cryptography.Pkcs. Он вводит крупные новые возможности, включая извлечение аннотаций, разбор HTML‑таблиц, OCR для арабского и корейского языков, Python‑логгер, обработку внешних ресурсов, обратные вызовы предварительного просмотра в виде обычных функций и командную строку groupdocs-parser. Пакет теперь представляет собой чистый Python‑пакет, поддерживающий Python 3.5 – 3.14, с обновлёнными тегами платформ (manylinux_2_27_x86_64, macosx_13_0_*) и без 32‑разрядного колеса Windows.

Что нового в этом выпуске

  • [Feature] Добавить поддержку извлечения аннотаций с помощью get_annotations() и TextOptions.include_annotations (PARSERPYTHONNET-23)
  • [Feature] Добавить командный инструмент groupdocs-parser (PARSERPYTHONNET-24)
  • [Feature] Добавить поддержку объекта Python‑логгера, реализующего ILogger (PARSERPYTHONNET-25)
  • [Feature] Добавить поддержку обработки загрузки внешних ресурсов из Python (PARSERPYTHONNET-26)
  • [Feature] Добавить OCR для арабского и корейского текста (PARSERPYTHONNET-27)
  • [Feature] Добавить поддержку извлечения таблиц из HTML‑документов (PARSERPYTHONNET-28)
  • [Feature] Добавить поддержку применения лицензии из переменной окружения GROUPDOCS_LIC_PATH (PARSERPYTHONNET-36)
  • [Enhancement] Обновить GroupDocs.Parser до 26.8 и встроенный рантайм до .NET 10.0.14 (PARSERPYTHONNET-29)
  • [Enhancement] Поставить чистый Python‑пакет для Python 3.5 – 3.14 вместо скомпилированного расширения (PARSERPYTHONNET-30)
  • [Enhancement] Передавать обратные вызовы предварительного просмотра в PreviewOptions как обычные функции Python (PARSERPYTHONNET-31)
  • [Enhancement] Отклонять присвоения неизвестных атрибутов объектов API (PARSERPYTHONNET-32)
  • [Enhancement] Обновить теги платформ до glibc 2.27 и macOS 13, удалить 32‑разрядное колесо Windows (PARSERPYTHONNET-33)
  • [Enhancement] Выбрасывать GroupDocsParserException и его подклассы вместо RuntimeError (PARSERPYTHONNET-34)
  • [Enhancement] Обновить System.Security.Cryptography.Pkcs до 10.0.14, что исправляет две уязвимости типа отказ в обслуживании (PARSERPYTHONNET-37)
  • [Fix] Некоторые документы Word и RTF завершаются с ошибкой The document appears to be corrupted или отсутствует сборка SkiaSharp 3.119 (PARSERPYTHONNET-35)
  • [Fix] Память растёт при открытии каждого документа из BytesIO (PARSERPYTHONNET-38)

Изменения публичного API

  • Ошибки движка теперь бросают GroupDocsParserException, InvalidPasswordException, CorruptedDocumentException или UnsupportedDocumentFormatException из groupdocs.parser.exceptions, тогда как в 25.12 для всех они бросали RuntimeError. Классы существовали в 25.12, но не наследовались от Exception и никогда не бросались. except Exception ловит ошибки обеих версий.
  • Присвоение неизвестного атрибута бросает AttributeError.
  • Списки, возвращаемые движком, поддерживают len() и индексацию, а пустой список считается ложным.

Удалено

  • groupdocs.parser.options.ICreatePageStream
  • groupdocs.parser.options.IReleasePageStream
  • groupdocs.parser.options.IPreviewPageRender

Передавайте функции в PreviewOptions и PreviewOptions.preview_page_render вместо этого.

Новые классы и члены

  • groupdocs.parser: Resources.
  • groupdocs.parser.data: AnnotationItem.
  • groupdocs.parser.options: CreatePageStream, ReleasePageStream, PreviewPageRender, Language, PreviewFormats.
  • Parser: get_annotations(), get_structure(), dispose().
  • Features: annotations.
  • TextOptions: include_annotations.
  • OcrOptions: language.
  • ILogger: error().
  • TocItem: extract_text().
  • PageTableArea: get() и table[row, column].
  • DocumentData, Template: get().
  • TemplateCollection: append().
  • Resources: storage_path, записываемый.

Новые возможности

Извлечение аннотаций

Parser.get_annotations() возвращает комментарии и заметки PDF, Word или PowerPoint‑документов в виде объектов AnnotationItem со значением, типом, индексом страницы, меткой времени, именем автора и инициалами; get_annotations(page_index) читает одну страницу. TextOptions.include_annotations добавляет текст аннотации к извлечённому тексту, а parser.features.annotations указывает, поддерживает ли формат аннотации.

from groupdocs.parser import Parser
from groupdocs.parser.options import TextOptions

with Parser("reviewed.docx") as parser:
    for note in parser.get_annotations() or []:
        print(note.page_index + 1, note.annotation_type, note.author_name, note.value.strip())

    options = TextOptions()
    options.include_annotations = True
    print(parser.get_text(options))

Командная строка

Колесо устанавливает консольный скрипт groupdocs-parser (также python -m groupdocs.parser) с командами text, info, metadata, images, annotations и list-formats. text принимает --page N (нумерация с 1), --format plain|markdown|html, --ocr, --include-annotations и -o FILE; info, metadata и annotations принимают --json; images принимает --out DIR; каждая команда принимает --password. --license и --version указываются перед командой. Код выхода 0 при успехе, 2 при ошибке пользователя (например, отсутствующий файл) и 1 при ошибке движка или неподдерживаемом формате.

groupdocs-parser text report.pdf --page 2 -o page2.txt
groupdocs-parser text report.docx --format markdown
groupdocs-parser info report.pdf --json
groupdocs-parser annotations reviewed.docx --json
groupdocs-parser --license license.lic text protected.pdf --password secret

Python‑логгер

Обычный объект Python с методами trace(message), warning(message) и error(message, exception) можно передать в ParserSettings как логгер, и движок будет вызывать его при возникновении событий, например повреждённого файла. Функция log(level, message, exception) тоже работает.

from groupdocs.parser import Parser
from groupdocs.parser.options import ParserSettings


class PrintLogger:
    def trace(self, message):
        print("TRACE:", message)

    def warning(self, message):
        print("WARNING:", message)

    def error(self, message, exception):
        print("ERROR:", message, exception)


with Parser("document.pdf", ParserSettings(PrintLogger())) as parser:
    print(parser.get_document_info().page_count)

Управление загрузкой внешних ресурсов

Движок запрашивает обработчик внешних ресурсов перед загрузкой каждой картинки, на которую ссылается HTML‑ или MHTML‑документ. Обработчиком может быть функция, объект с методом on_loading(args) или подкласс ExternalResourceHandler; установка args.skipped = True пропускает ресурс. ParserSettings принимает его как external_resource_handler.

from groupdocs.parser import Parser
from groupdocs.parser.options import ParserSettings


def skip_remote(args):
    args.skipped = args.uri.startswith("http")


with Parser("page.html", ParserSettings(external_resource_handler=skip_remote)) as parser:
    print(len(parser.get_images() or []))

OCR для арабского и корейского

OcrOptions.language выбирает алфавит, распознаваемый OCR; по умолчанию — английский. Language.ARA и Language.KOR новые в этом движке. Модели распознавания входят в состав движка: первый вызов OCR распаковывает их (~80 МБ) в папку aspose_data в рабочем каталоге, без загрузки из сети. Чтобы задать другую папку, установите Resources.storage_path (from groupdocs.parser import Resources) до первого вызова OCR.

from groupdocs.parser import Parser
from groupdocs.parser.options import Language, OcrOptions, TextOptions

ocr_options = OcrOptions()
ocr_options.language = Language.KOR
with Parser("scan.jpg") as parser:
    print(parser.get_text(TextOptions(False, True, ocr_options)))

Таблицы из HTML‑документов

get_tables() теперь находит таблицы в HTML‑документах, как это делалось для PDF, Word и электронных таблиц; в 25.12 их не находило. Ячейка доступна как table[row, column] или table.get(row, column).

from groupdocs.parser import Parser

with Parser("report.html") as parser:
    for table in parser.get_tables() or []:
        for row in range(table.row_count):
            print([table[row, column].text.rstrip("\x07") for column in range(table.column_count)])

Лицензия из переменной окружения

Установите GROUPDOCS_LIC_PATH в путь к файлу лицензии или к URL, откуда её можно получить, и лицензия будет применена при первом вызове Parser, без кода лицензии; в 25.12 переменная не читалась. Если лицензия не может быть применена (отсутствует файл, истёк срок подписки, лицензия для другого продукта), каждый вызов Parser бросает LicenseError, указывая переменную и причину движка, пока License().set_license() не применит лицензию. Установите GROUPDOCS_LIC_STRICT=0, чтобы получить одно LicenseWarning и режим оценки вместо этого.

from groupdocs.parser import LicenseError, Parser

try:
    with Parser("report.pdf") as parser:
        print(parser.get_text())
except LicenseError as e:
    print(e)  # GROUPDOCS_LIC_PATH=... could not be applied: <reason>

Обратные вызовы предварительного просмотра как обычные функции

PreviewOptions(create_page_stream, release_page_stream) принимает обычные функции, как и PreviewOptions.preview_page_render. create_page_stream(page_number) возвращает записываемый поток, например файл, открытый в режиме "wb" или io.BytesIO; нумерация страниц начинается с 1. Движок закрывает переданный файл и вызывает release_page_stream(page_number) после записи страницы. В 25.12 использовались классы ICreatePageStream, IReleasePageStream и IPreviewPageRender.

from groupdocs.parser import Parser
from groupdocs.parser.options import PreviewOptions


def create_page_stream(page_number):
    return open("page-%d.png" % page_number, "wb")


def release_page_stream(page_number):
    print("page", page_number, "written")


options = PreviewOptions(create_page_stream, release_page_stream)
options.preview_page_render = lambda info: print("rendering page", info.page_number)
with Parser("document.pdf") as parser:
    parser.generate_preview(options)

Ошибочные атрибуты бросают AttributeError

Присвоение свойства, которого нет у объекта API, бросает AttributeError с подсказкой «Did you mean». В 25.12 такое присвоение принималось, сохранялся только Python‑атрибут, а настройка движка оставалась без изменений.

from groupdocs.parser.options import TextOptions

options = TextOptions()
try:
    options.include_annotation = True
except AttributeError as error:
    print(error)

Одно колесо для Python 3.5 – 3.14

В 25.12 использовалось скомпилированное расширение, с отдельным бинарным модулем для каждой версии Python и рантаймом .NET Core 3.1. В 26.10 — одно колесо py3-none-<platform> на платформу, чистый Python поверх встроенного .NET 10, и объявление python_requires=">=3.5,<3.15". Python 3.14 новый: в 25.12 было <3.14. Большинство кода 25.12 работает без изменений, и все 129 примеров Docs, которые работали в 25.12, работают в 26.10. get_text() и get_formatted_text() по‑прежнему возвращают str, который теперь также поддерживает read_to_end().

Обновлённые теги платформ и 64‑разрядное колесо Windows

Linux‑колесо имеет тег manylinux_2_27_x86_64 — самая старая glibc, на которой запускается встроенный .NET 10, а macOS‑колёса — macosx_13_0_x86_64 и macosx_13_0_arm64. 32‑разрядного колеса Windows больше нет. Установка требует pip 20.3 или новее.

Пример кода

Извлечение аннотаций из Word‑документа и включение их в извлечённый текст:

from groupdocs.parser import Parser
from groupdocs.parser.options import TextOptions

with Parser("reviewed.docx") as parser:
    for note in parser.get_annotations() or []:
        print(note.page_index + 1, note.annotation_type, note.author_name, note.value.strip())

    options = TextOptions()
    options.include_annotations = True
    print(parser.get_text(options))

Как получить обновление

PyPI

Установите или обновите через PyPI:

groupdocs-parser-net 26.10.0 на PyPI

pip install groupdocs-parser-net==26.10.0

Прямая загрузка

Скачайте колёса, специфичные для платформы, со страницы выпуска GroupDocs.Parser for Python via .NET 26.10:

Ресурсы