Полный рабочий пример доступен на GitHub:
manage-xmp-in-psd-and-ai-files-python
Введение
Маркетинговая команда загружает 400 PSD‑файлов в вашу платформу активов. Загрузка проходит успешно. Поиск не работает, потому что ни один файл не содержит ключевых слов, у половины отсутствует уведомление об авторских правах, а имена дизайнеров находятся только в какой‑то таблице. Решение — не более крупная таблица. Управление XMP — это возможность GroupDocs.Metadata для Python через .NET, которая читает и записывает пакет метаданных, встроенный в файлы Photoshop PSD и Illustrator AI, что позволяет хранить данные о праве собственности и поиске непосредственно в файлах.
XMP — это XML‑пакет внутри бинарного контейнера, организованный в схемы: Dublin Core — поля, понятные любой системе, схема Photoshop — редакционный контекст, XmpBasic — идентификация инструмента. Разобрать PSD вручную, чтобы добраться до этого пакета, действительно сложно. С классом Metadata это три обращения к атрибутам, и тот же код работает и с AI‑файлами.
Этот учебник демонстрирует полный цикл в четырёх шагах: сделать снимок всего пакета, прочитать важные схемы, записать авторские права и создателя, а также добавить ключевые слова для поиска. Каждый фрагмент кода берётся из исполняемого репозитория, который проверяет, что записанные значения сохраняются.
Необходимые условия
Прежде чем начать, убедитесь, что у вас есть:
- Python 3 с pip
- GroupDocs.Metadata для Python через .NET (в репозитории зафиксирована версия 26.5)
- PSD‑ или AI‑файл для экспериментов
Установка
pip install groupdocs-metadata-net==26.5
Шаг 1 — Снимок всего XMP пакета
Начните с просмотра всего, что содержит файл. Снимок проходит по корневому пакету, каждой зарегистрированной схеме и, наконец, сканирует дерево свойств в поисках чего‑нибудь нестандартного, собирая всё в один плоский словарь.
result = {}
def put(props, prop):
value = (str(prop.interpreted_value) if prop.interpreted_value is not None
else (str(prop.value) if prop.value is not None else ""))
props[prop.name] = value
with Metadata("campaign-hero.psd") as metadata:
root = metadata.get_root_package()
xmp = getattr(root, "xmp_package", None)
if xmp is not None:
for p in xmp: # свойства корневого пакета
put(result, p)
schemes = xmp.schemes
for scheme in (schemes.dublin_core, schemes.xmp_basic, schemes.photoshop,
schemes.camera_raw, schemes.paged_text,
schemes.xmp_dynamic_media, schemes.xmp_media_management):
if scheme is None:
continue
for p in scheme:
put(result, p)
for p in metadata.find_properties(lambda p: p.name is not None):
if p.name not in result: # захват пользовательских пакетов
put(result, p)
Ключевые моменты:
- Сначала
interpreted_value: даты и перечисления приходят в человекочитаемом виде, а не в сыром виде. - Семь схем плюс сканирование: завершающий проход
find_propertiesловит пакеты поставщиков, которые не охвачены именованными схемами. - Открыт только один файл: весь снимок выполняется в едином контексте
Metadata, что важно при массовом вводе.
Подсказка: индексируйте этот словарь во время ввода, и большинство последующих вопросов к метаданным превращаются в поиск по словарю вместо чтения файлов.
Какую схему XMP должна сначала читать моя интеграция?
Начните с Dublin Core. Его девять полей dc: содержат заголовок, создателя, права и тему — значения, которые согласованы большинством DAM‑систем, поисковых индексов и проверок лицензий, и оба формата — PSD и AI — представляют их одинаково. Затем читайте схему Photoshop для редакционного контекста, например City, Credit и DateCreated. Полный скан пакета оставьте для задач ввода, которым необходимо захватить всё.
Шаг 2 — Чтение схем, отвечающих на реальные вопросы
Для кода, работающего по запросу, ограничьте чтение одной схемой. Dublin Core отвечает на вопросы о праве собственности и поиске:
dc_fields = {}
with Metadata("campaign-hero.psd") as metadata:
xmp = getattr(metadata.get_root_package(), "xmp_package", None)
dc = xmp.schemes.dublin_core if xmp is not None else None
if dc is not None:
for p in dc:
dc_fields[p.name] = (str(p.interpreted_value)
if p.interpreted_value is not None else
str(p.value) if p.value is not None else "")
print(dc_fields.get("dc:rights", "<no rights recorded>"))
Схема Photoshop работает аналогично через типизированные свойства: ps.color_mode, ps.icc_profile, ps.city, ps.country, ps.date_created, ps.caption_writer, ps.credit и ps.source, каждое читается с проверкой на None. Именно эти поля используют Bridge, Lightroom и фильтры поиска DAM для файлов Adobe.
Обратите внимание, что происходит с файлами без XMP: проверки возвращают пустой словарь, а не исключение. Свежо экспортированные активы часто попадают в эту ситуацию, поэтому сохраняйте такое поведение в своей интеграции.
Тот же набор трёх запросов работает и с файлами Illustrator. Поменяйте campaign-hero.psd на brand-mark.ai, и ничего больше не меняется — это делает один путь кода реальным для смешанных архивов Adobe. На практике свежий экспорт AI обычно содержит меньше заполненных схем, чем сохранение Photoshop, поэтому путь с пустым словарём вызывается чаще.
Шаг 3 — Запись авторских прав и создателя
Теперь путь записи. Маркировка собственности затрагивает три поля, чтобы каждый читатель видел одинаковую информацию: dc:rights — юридическое уведомление, dc:creator — упорядоченный список, и xmp:CreatorTool — инструмент, читающий схему XmpBasic вместо Dublin Core. Однажды я потерял полдня, пытаясь избавиться от баннера лицензии «Неизвестный автор» в активах, которые дизайнеры уверяли, что пометили; значения находились в dc:creator, а инструмент читал только xmp:CreatorTool. Запись обоих полей устранила эту категорию багов.
with Metadata("campaign-hero.psd") as metadata:
root = metadata.get_root_package()
xmp = getattr(root, "xmp_package", None)
if xmp is None: # файл вообще не имеет XMP
root.xmp_package = XmpPacketWrapper()
xmp = root.xmp_package
if xmp.schemes.dublin_core is None:
xmp.schemes.dublin_core = XmpDublinCorePackage()
dc = xmp.schemes.dublin_core
dc.set_rights("(C) 2026 GroupDocs Sample")
dc.set("dc:creator", XmpArray.from_(["Digital Asset Team"],
XmpArrayType.ORDERED))
if xmp.schemes.xmp_basic is None:
xmp.schemes.xmp_basic = XmpBasicPackage()
xmp.schemes.xmp_basic.creator_tool = "Digital Asset Team"
metadata.save("campaign-hero-stamped.psd")
Ключевые моменты:
- Проверки создают недостающие уровни:
XmpPacketWrapperиXmpDublinCorePackageсоздаются по требованию, поэтому запись работает и в файлах без XMP. - Упорядоченный массив для создателей: порядок авторов имеет значение, поэтому список создателей использует упорядоченный
XmpArray. - Сохранение в новый путь: исходный файл остаётся нетронутым, что является правильным поведением по умолчанию при экспортных шагах.
Шаг 4 — Тегирование ключевых слов для поиска
dc:subject — это набор ключевых слов для индексов DAM. Запись заменяет весь набор одним вызовом:
with Metadata("campaign-hero.psd") as metadata:
root = metadata.get_root_package()
xmp = getattr(root, "xmp_package", None)
if xmp is None:
root.xmp_package = XmpPacketWrapper()
xmp = root.xmp_package
if xmp.schemes.dublin_core is None:
xmp.schemes.dublin_core = XmpDublinCorePackage()
xmp.schemes.dublin_core.set(
"dc:subject",
XmpArray.from_(["landscape", "sunset", "commercial"],
XmpArrayType.UNORDERED))
metadata.save("campaign-hero-tagged.psd")
Ключевые слова используют массив UNORDERED, потому что порядок не важен для индексатора. Поскольку set заменяет существующий набор, сначала прочитайте текущие ключевые слова и объедините их в Python, если вам нужно добавить, а не заменить.
Чтобы проверить любую запись, повторно выполните читатель Шага 2 над полученным файлом. Репозиторий автоматизирует именно это: он перечитывает свои выводы и проверяет, что строка авторских прав и первое ключевое слово сохраняются в записанных байтах.
Примеры из реального мира
Ввод в DAM
Запускайте снимок Шага 1 для каждого входящего файла и сохраняйте словарь вместе с записью актива. Поиск, дедупликация и проверки прав затем выполняются против вашей базы данных, а не при повторном открытии бинарных файлов. Снимок небольшого образца PSD из репозитория уже возвращает здоровый набор свойств за один проход, и тот же вызов сохраняет свою форму, когда входные данные превращаются в папку из тысяч файлов.
Применение лицензий
Перед тем как актив будет отправлен в клиентский портал, требуйте непустое dc:rights. Файлы, у которых это поле пустое, автоматически проходят обработку Шага 3, поэтому ничего не покидает систему без уведомления.
Массовое пере‑тегирование
Когда меняется таксономия, прочитайте dc:subject каждого файла, сопоставьте старые термины с новыми в Python и запишите объединённый набор обратно с помощью Шага 4. И PSD, и AI‑архивы обрабатываются одним и тем же циклом. Никакой лицензии Photoshop не требуется.
Лучшие практики и советы
- Считать пустоту нормой: файлы без XMP — обычное дело, а не ошибка; шаблон раннего возврата поддерживает плавность конвейеров.
- Объединять перед записью ключевых слов:
setзаменяетdc:subject, поэтому добавление подразумевает чтение, расширение, запись. - Записывать идентификацию в обе схемы: сопоставление
dc:creatorсxmp:CreatorToolобеспечивает согласованность между читателями Dublin Core и XmpBasic. - Проверять записи повторным чтением: повторный читатель после сохранения дешёв и сразу выявляет неожиданные изменения контейнера.
- Лицензировать для продакшна: режим оценки работает для всех показанных примеров; используйте лицензию перед тем, как ставить штамп на реальные клиентские активы.
Заключение
Чтение и запись XMP в файлах Adobe сводится к трем действиям: получить пакет через get_root_package(), проверить наличие нужной схемы и прочитать или записать типизированные значения. С этими действиями вы построили полный цикл в этом учебнике — от снимка пакета до чтения схем, маркировки авторских прав и тегирования ключевых слов, используя один и тот же код для PSD и AI файлов.
Готовы внедрить это в свой проект? Следующие шаги:
- Прочитайте документацию Работа с XMP‑метаданными для обновления и удаления пакетов
- Ознакомьтесь с руководством по использованию в интеграциях на основе того же репозитория
- Склонируйте пример проекта и запустите его на своих активах
Дополнительные ресурсы
- GroupDocs.Metadata Documentation
- API Reference
- Sample Projects on GitHub
- GroupDocs.Metadata Blog Category
Вопросы о вашем XMP‑рабочем процессе? Спросите на форуме поддержки.