Я хотел бы использовать 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?






Я не знаю 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 и извлечь из него все.
@КейДжей, да. Я считаю, что это справедливо и здесь, поскольку как только вы получите корневой объект минидома, вы сможете получить все, что в нем есть.
Спасибо, это интересно. Но PyPDF2 устарел (мне нужно устойчивое решение). Документы PyPDF2 предлагают использовать pypdf. LMC отметил выше, что я начал с вопроса о pypdf, но ответ на него, похоже, мне не помог. Итак, я попробовал xmptools. Оба пакета, похоже, создают график RDF для метаданных XMP. Итак, похоже, я попал в такое же затруднительное положение (возможно, мне нужно задать еще один вопрос!).
Ответ @Blair обновлен для использования pypdf 4.2.0 (последняя версия), и ответ работает «из коробки». Фактически код, связанный с xmp, выглядит так же, как и другой модуль.
@LMC, отлично! Да, это выглядит очень многообещающе. Я не могу сразу уделить этому время, но думаю, это поможет. Кстати, вы используете meta.dc_identifier до того, как meta был определен выше.
Я приму это как ответ. Это не совсем ответ на вопрос, который я задал, но это потому, что я изо всех сил пытался сформулировать хороший вопрос! Эта информация очень полезна и позволит мне добиться прогресса. -- Спасибо
Я просто собираюсь предоставить метод для извлечения полного 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
KJ, похоже, вы не отвечаете на вопрос (есть ли у xmptools способ читать простые записи, в которых не использовались теги RDF?). Или, возможно, вы говорите НЕТ, данные необходимо рассматривать как необработанный XML. Что он? Я хочу понять, почему такие инструменты, как
xmptoolsиpypdf, похоже, не способны извлекать информацию из такого рода данных XMP. Оба (если я правильно понимаю) создают график RDF (xmpв моем примере выше), который затем используется для доступа к конкретной информации.