Получение метаданных XMP из файлов PDF с помощью инструментов Python xmptools

Я хотел бы использовать Python для получения метаданных, хранящихся в файлах PDF. Я пытаюсь использовать Python xmptools, но не могу извлечь все метаданные. Например, эта статья доступна в формате PDF. У меня есть следующий скрипт, который пытается извлечь метаданные

from xmptools import XMPMetadata, DC
xmp = XMPMetadata.fromFile("Leonard_2015_Comment_on_‘Dimensionless_units_in_the_SI’.pdf")[0]
print( xmp.getContainerItems(DC.publisher) )

Это работает нормально. Результат [rdflib.term.Literal('IOP Publishing')]. Однако, если я изменю последнюю строку на

print( xmp.getContainerItems(DC.identifier) )

то в результате я получаю None.

Я думаю, это может быть связано с XML внутри PDF-файла. Данные, относящиеся к этим двум запросам:

        <dc:publisher>
            <rdf:Bag>
               <rdf:li>IOP Publishing</rdf:li>
            </rdf:Bag>
         </dc:publisher>
     <dc:identifier>doi:10.1088/0026-1394/52/4/613</dc:identifier>

В случае publisher информация заключена в теги RDF, но в случае identifier это не так.

Есть ли способ xmptools прочитать простые записи, в которых не использовались теги RDF?

KJ, похоже, вы не отвечаете на вопрос (есть ли у xmptools способ читать простые записи, в которых не использовались теги RDF?). Или, возможно, вы говорите НЕТ, данные необходимо рассматривать как необработанный XML. Что он? Я хочу понять, почему такие инструменты, как xmptools и pypdf, похоже, не способны извлекать информацию из такого рода данных XMP. Оба (если я правильно понимаю) создают график RDF (xmp в моем примере выше), который затем используется для доступа к конкретной информации.

Blair 06.05.2024 22:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
246
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я не знаю xmptools, но, может быть, pdfminer-six может помочь?

from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage

fp = open('example.pdf', 'rb')
parser = PDFParser(fp)
doc = PDFDocument(parser)

print(doc.info)
Ответ принят как подходящий

pypdf имеет доступ к метаданным PDF. Конкретные атрибуты перечислены в готовом виде, или можно получить и повторить корневой объект минидома.

from pypdf import PdfReader
fd = open("/home/lmc/tmp/shapes.pdf", "rb")
reader = PdfReader(fd)
meta = reader.xmp_metadata   
meta.dc_identifier

Результат:

'doi:1.1.1.1.1.'

Получение корневого объекта минидома

meta = reader.xmp_metadata

root = meta.rdf_root

print(type(root))
print(root.toxml())

Результат

<class 'xml.dom.minidom.Element'>
<rdf:RDF xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <rdf:Description xmlns:pdfaid = "http://www.aiim.org/pdfa/ns/id/" rdf:about = "">
   <pdfaid:part>3</pdfaid:part>
   <pdfaid:conformance>B</pdfaid:conformance>
  </rdf:Description>
  <rdf:Description xmlns:dc = "http://purl.org/dc/elements/1.1/" rdf:about = "">

   <!-- redacted -->

   <xmp:MetadataDate>2024-05-06T19:20:03-03:00</xmp:MetadataDate>
  </rdf:Description>
 </rdf:RDF>

Получение конкретных элементов

for node in root.getElementsByTagName('xmp:ModifyDate'):
    print(node.firstChild.nodeValue, node.toxml())

for node in root.getElementsByTagNameNS('http://ns.adobe.com/xap/1.0/', 'ModifyDate'):
    print(node.firstChild.nodeValue, node.toxml())

результат

2024-05-06T19:20:03-03:00 <xmp:ModifyDate>2024-05-06T19:20:03-03:00</xmp:ModifyDate>
2024-05-06T19:20:03-03:00 <xmp:ModifyDate>2024-05-06T19:20:03-03:00</xmp:ModifyDate>

Кроме того, используя pyxml2xpath, получите все выражения xpath из метаданных (XML), чтобы узнать, какие элементы присутствуют, без анализа поэлементно.

# pip install pyxml2xpath==0.3.3

from xml2xpath import xml2xpath
tree, ns, xmap = xml2xpath.fromstring(root.toxml())

# get specific element
mod_date = tree.xpath('//rdf:Description/xmp:ModifyDate', namespaces=ns)[0]
print('ModifyDate', mod_date.text)

# print all found elements
xml2xpath.print_xpaths(xmap, 'all')

Результат (отредактировано)

ModifyDate 2024-05-06T19:20:03-03:00

/rdf:RDF
/rdf:RDF/rdf:Description[1]
/rdf:RDF/rdf:Description[1]/@{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about
/rdf:RDF/rdf:Description[1]/pdfaid:part
/rdf:RDF/rdf:Description[1]/pdfaid:conformance
/rdf:RDF/rdf:Description[2]
/rdf:RDF/rdf:Description[2]/@{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about
/rdf:RDF/rdf:Description[2]/dc:format
/rdf:RDF/rdf:Description[2]/dc:title

/rdf:RDF/rdf:Description[2]/dc:rights
/rdf:RDF/rdf:Description[2]/dc:rights/rdf:Alt
/rdf:RDF/rdf:Description[2]/dc:rights/rdf:Alt/rdf:li
/rdf:RDF/rdf:Description[2]/dc:rights/rdf:Alt/rdf:li/@{http://www.w3.org/XML/1998/namespace}lang
/rdf:RDF/rdf:Description[2]/dc:type
/rdf:RDF/rdf:Description[3]
/rdf:RDF/rdf:Description[3]/@{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about
/rdf:RDF/rdf:Description[3]/pdf:Producer
/rdf:RDF/rdf:Description[3]/pdf:Keywords
/rdf:RDF/rdf:Description[3]/pdf:PDFVersion
/rdf:RDF/rdf:Description[4]
/rdf:RDF/rdf:Description[4]/@{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about
/rdf:RDF/rdf:Description[4]/xmp:CreatorTool
/rdf:RDF/rdf:Description[4]/xmp:CreateDate
/rdf:RDF/rdf:Description[4]/xmp:ModifyDate
/rdf:RDF/rdf:Description[4]/xmp:MetadataDate

Found  38 xpath expressions for elements
Found   7 xpath expressions for attributes

@KJ, ты можешь получить корневой элемент xml.dom.minidom.Element и извлечь из него все.

LMC 07.05.2024 00:34

@КейДжей, да. Я считаю, что это справедливо и здесь, поскольку как только вы получите корневой объект минидома, вы сможете получить все, что в нем есть.

LMC 07.05.2024 01:12

Спасибо, это интересно. Но PyPDF2 устарел (мне нужно устойчивое решение). Документы PyPDF2 предлагают использовать pypdf. LMC отметил выше, что я начал с вопроса о pypdf, но ответ на него, похоже, мне не помог. Итак, я попробовал xmptools. Оба пакета, похоже, создают график RDF для метаданных XMP. Итак, похоже, я попал в такое же затруднительное положение (возможно, мне нужно задать еще один вопрос!).

Blair 07.05.2024 03:48

Ответ @Blair обновлен для использования pypdf 4.2.0 (последняя версия), и ответ работает «из коробки». Фактически код, связанный с xmp, выглядит так же, как и другой модуль.

LMC 07.05.2024 14:49

@LMC, отлично! Да, это выглядит очень многообещающе. Я не могу сразу уделить этому время, но думаю, это поможет. Кстати, вы используете meta.dc_identifier до того, как meta был определен выше.

Blair 07.05.2024 23:54

Я приму это как ответ. Это не совсем ответ на вопрос, который я задал, но это потому, что я изо всех сил пытался сформулировать хороший вопрос! Эта информация очень полезна и позволит мне добиться прогресса. -- Спасибо

Blair 11.05.2024 04:36

Я просто собираюсь предоставить метод для извлечения полного XMP из PDF-файла. Лично я считаю, что XML-метод специальных вложенных строк менее чем полезен, но с помощью Python или любого другого редактора XMP вы можете преобразовать XMP.XML в более полезный вывод.

Итак, на платформе Xross одним PDF-инструментом, который может извлекать PDF-объекты, является MuTool (основа PyMuPDF).

Я использую Windows, поэтому мне нужен cmd-файл для извлечения или индивидуального манипулирования данными
getxmp.cmd

@echo off
set "mutool=C:\Users\lez\Downloads\Apps\PDF\mupdf\1.20.0\Mutool.exe"

"%mutool%" show "%~1" | find "/Root" >"%temp%\temp$.tmp"
set /P Object$=<"%temp%\temp$.tmp"
for /F "tokens=2 delims= " %%R in ("%Object$%") do ("%mutool%" show "%~1" %%R | find "/Metadata") >"%temp%\temp$.tmp"
if errorlevel==1 echo /Metadata not found&& type "%temp%\temp$.tmp"&& pause&& del "%temp%\temp$.tmp"&& exit /b
set /P Object$=<"%temp%\temp$.tmp"
for /F "tokens=2 delims=:" %%C in ('chcp') do set /a oldcp =%%C&&chcp 65001 >nul
for /F "tokens=2 delims= " %%M in ("%Object$%") do "%mutool%" show -b -o "%~1.xmp" "%~1" %%M
del "%temp%\temp$.tmp"

REM post processing as desired here exclusions
if not [%1]==[] type "%~1.xmp" ^
 | find /i /v "xmpmeta" ^
 | find /i /v "xmlns" ^
 | find /i /v "bag" ^
 | find /i /v "seq" ^
 | find /i /v "xpacket" ^
 | find /i /v "rdf:RDF" ^
 | find ":"
if not [%2]==[] type "%~1.xmp" | find /i /v "xmpmeta" | find /i /v "xmlns" | find /i /v "bag" | find /i /v "seq" | find /i "%2" 

chcp %oldcp% >nul
pause

Это позволяет перетаскивать PDF-файл для получения данных в файле боковой машины name.pdf.xmp или через консоль добавлять другие переключатели и редактировать результат по желанию. Однако каждый PDF-файл может иметь разную структуру XMP или не иметь метаданных.

Еще одна полезная платформа Xross Инструмент метаданных XMP — ExifTool

ExifTool извлечет информацию XMP, даже если она не указана в

Это легко настраивается для перетаскивания, поэтому, если имя файла exiftool(-a -U -g1 -w xmp).exe, результат будет структурирован следующим образом. comment.xmp (возможно, мне не следовало использовать расширение xmp!)

---- ExifTool ----
ExifTool Version Number         : 12.84
---- System ----
File Name                       : Comment.pdf
Directory                       : C:/Users/lez/Downloads/Apps/PDF/mupdf/1.20.0
File Size                       : 295 kB
Zone Identifier                 : Exists
File Modification Date/Time     : 2024:05:07 03:16:36+01:00
File Access Date/Time           : 2024:05:07 15:39:46+01:00
File Creation Date/Time         : 2024:05:07 03:16:33+01:00
File Permissions                : -rw-rw-rw-
---- File ----
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
---- PDF ----
PDF Version                     : 1.4
Linearized                      : No
Author                          : B P Leonard
Create Date                     : 2015:07:30 20:24:16+05:30
Creator                         : Adobe InDesign CS5.5 (7.5)
Cross Mark Domains 1            : iop.org
Cross Mark Major Version Date   : 2015-8-3
Crossmark Domain Exclusive      : true
Modify Date                     : 2015:08:04 11:18:41+01:00
Producer                        : Adobe PDF Library 9.9
Subject                         : Metrologia, 52 (2015) 613. doi: 10.1088/0026-1394/52/4/613
Title                           : Comment on ‘Dimensionless units in the SI’
Trapped                         : False
Doi                             : 10.1088/0026-1394/52/4/613
Robots                          : noindex
Rgid                            : PB:280873495_AS:314881943769089@1452085113684
Page Count                      : 6
---- XMP-x ----
XMP Toolkit                     : Adobe XMP Core 5.4-c005 78.147326, 2012/08/23-13:03:03
---- XMP-pdfx ----
Doi                             : 10.1088/0026-1394/52/4/613
Robots                          : noindex
Cross Mark Major Version Date   : 2015-8-3
Crossmark Domain Exclusive      : true
Cross Mark Domains              : iop.org
---- XMP-xmp ----
Creator Tool                    : Adobe InDesign CS5.5 (7.5)
Create Date                     : 2015:07:30 20:24:16+05:30
Modify Date                     : 2015:08:04 11:18:41+01:00
Metadata Date                   : 2015:08:04 11:18:41+01:00
---- XMP-xmpRights ----
Marked                          : True
---- XMP-dc ----
Format                          : application/pdf
Identifier                      : doi:10.1088/0026-1394/52/4/613
Title                           : Comment on ‘Dimensionless units in the SI’
Creator                         : B P Leonard
Publisher                       : IOP Publishing
Description                     : Metrologia, 52 (2015) 613. doi: 10.1088/0026-1394/52/4/613
---- XMP-prism ----
Aggregation Type                : journal
Publication Name                : Metrologia
Copyright                       : © 2015 BIPM & IOP Publishing Ltd
ISSN                            : 0026-1394
Starting Page                   : 613
Ending Page                     : 616
Page Range                      : 613
Digital Object Identifier       : 10.1088/0026-1394/52/4/613
URL                             : http://dx.doi.org/10.1088/0026-1394/52/4/613
---- XMP-crossmark_1_ ----
Major Version Date              : 2015-8-3
Crossmark Domain Exclusive      : true
Doi                             : 10.1088/0026-1394/52/4/613
Cross Mark Domains              : iop.org
---- XMP-pdf ----
Producer                        : Adobe PDF Library 9.9
Trapped                         : False
---- XMP-xmpMM ----
Document ID                     : uuid:411519c7-630a-4745-9153-f20c68b14cfe
Instance ID                     : uuid:4152b40e-9ef3-4b46-8557-a7d2dbfa40b9

У exiftool так много опций, что сложно сказать, что вам может понадобиться. Однако его можно настроить на вывод в формате CSV или удаление дубликатов выходных данных, но, как и в случае с дегустатором, здесь есть один командный файл и его выходные данные (с дубликатами). mymeta.cmd

@echo off
set "exif=C:\Users\lez\Downloads\Apps\PDF\mupdf\1.20.0\exiftool(-a -U -g1 -w! .pdf.xmp.txt).exe"

"%exif%" "%~1" 2>nul
type "%~1.xmp.txt" |find /i "title"             >metadata.txt
type "%~1.xmp.txt" |find /i "author"            >>metadata.txt
type "%~1.xmp.txt" |find /i "publisher"         >>metadata.txt
type "%~1.xmp.txt" |findstr /r /i "^identifier" >>metadata.txt
type "%~1.xmp.txt" |find /i "producer"          >>metadata.txt

Таким образом, чтобы найти издателя DC, вы экспортируете строку

Publisher                       : IOP Publishing

Другие вопросы по теме