|
|
@ -1,68 +1,135 @@
|
|
|
|
#!/bin/bash
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
"""Get OCR results as a OCR-D workspace for a given PPN"""
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import lxml.etree as ET
|
|
|
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
from copy import deepcopy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XMLNS = {
|
|
|
|
|
|
|
|
'mets': 'http://www.loc.gov/METS/',
|
|
|
|
|
|
|
|
'xlink': 'http://www.w3.org/1999/xlink'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
API_URL = 'https://digital.staatsbibliothek-berlin.de/oai'
|
|
|
|
|
|
|
|
IDENTIFIER_TEMPLATE = 'oai:digital.staatsbibliothek-berlin.de:%s'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for prefix, uri in XMLNS.items():
|
|
|
|
|
|
|
|
ET.register_namespace(prefix, uri)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# XXX
|
|
|
|
|
|
|
|
# show_help() {
|
|
|
|
|
|
|
|
# cat <<-EOH
|
|
|
|
|
|
|
|
# Usage: $0 PPN77164308X
|
|
|
|
|
|
|
|
#
|
|
|
|
# Get OCR results as a OCR-D workspace for a given PPN
|
|
|
|
# Get OCR results as a OCR-D workspace for a given PPN
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# Options:
|
|
|
|
|
|
|
|
# --help Show this message and exit.
|
|
|
|
|
|
|
|
# EOH
|
|
|
|
|
|
|
|
# }
|
|
|
|
|
|
|
|
|
|
|
|
set -e # Abort on error
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def oai_mets(ppn):
|
|
|
|
|
|
|
|
"""Retrieve METS metadata for a given PPN."""
|
|
|
|
|
|
|
|
|
|
|
|
show_help() {
|
|
|
|
params = {
|
|
|
|
cat <<-EOH
|
|
|
|
'verb': 'GetRecord',
|
|
|
|
Usage: $0 PPN77164308X
|
|
|
|
'metadataPrefix': 'mets',
|
|
|
|
|
|
|
|
'identifier': IDENTIFIER_TEMPLATE % ppn
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Get OCR results as a OCR-D workspace for a given PPN
|
|
|
|
s = requests.Session()
|
|
|
|
|
|
|
|
r = s.get(API_URL, params=params)
|
|
|
|
|
|
|
|
mets = ET.XML(r.content).find(f".//{{{XMLNS['mets']}}}mets")
|
|
|
|
|
|
|
|
mets = ET.ElementTree(mets)
|
|
|
|
|
|
|
|
|
|
|
|
Options:
|
|
|
|
return mets
|
|
|
|
--help Show this message and exit.
|
|
|
|
|
|
|
|
EOH
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
make_workspace () {
|
|
|
|
|
|
|
|
ppn=$1
|
|
|
|
|
|
|
|
workspace=$2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def make_workspace(ppn, workspace):
|
|
|
|
# Make workspace directory
|
|
|
|
# Make workspace directory
|
|
|
|
mkdir "$workspace"
|
|
|
|
os.mkdir(workspace)
|
|
|
|
cd "$workspace"
|
|
|
|
os.chdir(workspace)
|
|
|
|
|
|
|
|
|
|
|
|
# Get METS from OAI-PMH
|
|
|
|
mets = oai_mets(ppn)
|
|
|
|
oai_identifier="oai%3Adigital.staatsbibliothek-berlin.de%3A$ppn"
|
|
|
|
|
|
|
|
oai_url="https://digital.staatsbibliothek-berlin.de/oai?verb=GetRecord&metadataPrefix=mets&identifier=$oai_identifier"
|
|
|
|
|
|
|
|
echo "$oai_url"
|
|
|
|
|
|
|
|
curl "$oai_url" | xmlstarlet sel -t -c '//*[local-name()="mets"]' > mets.xml
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Fix 'file:/' URLs to 'file:///'
|
|
|
|
# XXX
|
|
|
|
sed -i 's#file:/\([^/]\)#file:///\1#' mets.xml
|
|
|
|
# Delete PRESENTATION file group
|
|
|
|
|
|
|
|
# (local file:/// links, not handled well by "ocrd workspace")
|
|
|
|
|
|
|
|
for bad in mets.xpath('//mets:fileGrp[@USE="PRESENTATION"]', namespaces=XMLNS):
|
|
|
|
|
|
|
|
bad.getparent().remove(bad)
|
|
|
|
|
|
|
|
|
|
|
|
# Patch mets.xml to use our NFS mount
|
|
|
|
|
|
|
|
sed -i 's#file:///goobi/tiff001/sbb/#file:///srv/digisam_images/sbb/#g' mets.xml
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Remove LOCAL file group as we do not have access to the files
|
|
|
|
# Duplicate DEFAULT file group into a new file group BEST
|
|
|
|
ocrd workspace remove-group -rf --keep-files LOCAL
|
|
|
|
file_grp_default = mets.find('//mets:fileGrp[@USE="DEFAULT"]', namespaces=XMLNS)
|
|
|
|
|
|
|
|
file_grp_best = deepcopy(file_grp_default)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
file_grp_best.attrib['USE'] = 'BEST'
|
|
|
|
|
|
|
|
for f in file_grp_best.findall('./mets:file', namespaces=XMLNS):
|
|
|
|
|
|
|
|
old_id = f.attrib['ID']
|
|
|
|
|
|
|
|
new_id = re.sub('DEFAULT', 'BEST', old_id)
|
|
|
|
|
|
|
|
f.attrib['ID'] = new_id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for fptr in mets.findall(f'//mets:fptr[@FILEID="{old_id}"]', namespaces=XMLNS):
|
|
|
|
|
|
|
|
new_fptr = deepcopy(fptr)
|
|
|
|
|
|
|
|
new_fptr.attrib['FILEID'] = new_id
|
|
|
|
|
|
|
|
fptr.getparent().append(new_fptr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# XXX Need to fumble around with the URL for now
|
|
|
|
|
|
|
|
flocat = f.find(f".//{{{XMLNS['mets']}}}FLocat")
|
|
|
|
|
|
|
|
old_url = flocat.attrib[f"{{{XMLNS['xlink']}}}href"]
|
|
|
|
|
|
|
|
m = re.search(r'/dms/.*/([0-9]+)\.jpg$', old_url)
|
|
|
|
|
|
|
|
if m:
|
|
|
|
|
|
|
|
page_num = m.group(1)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
raise ValueError(f"Unexpected DEFAULT URL {old_url}")
|
|
|
|
|
|
|
|
url_iiif_full = f'https://content.staatsbibliothek-berlin.de/dc/{ppn}-{page_num}/full/full/0/default.jpg'
|
|
|
|
|
|
|
|
flocat.attrib[f"{{{XMLNS['xlink']}}}href"] = url_iiif_full
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mets.find('//mets:fileSec', namespaces=XMLNS).append(file_grp_best)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Write mets.xml
|
|
|
|
|
|
|
|
mets.write('mets.xml', pretty_print=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO
|
|
|
|
# Validate workspace
|
|
|
|
# Validate workspace
|
|
|
|
ocrd workspace validate mets.xml | grep -v "<notice>Won't download remote image"
|
|
|
|
#ocrd workspace validate mets.xml | grep -v "<notice>Won't download remote image"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# XXX
|
|
|
|
|
|
|
|
# Fix 'file:/' URLs to 'file:///'
|
|
|
|
|
|
|
|
#sed -i 's#file:/\([^/]\)#file:///\1#' mets.xml
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Patch mets.xml to use our NFS mount
|
|
|
|
|
|
|
|
#sed -i 's#file:///goobi/tiff001/sbb/#file:///srv/digisam_images/sbb/#g' mets.xml
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Command line parameters
|
|
|
|
# Command line parameters
|
|
|
|
OPTS=`getopt -o h --long help -- "$@"`
|
|
|
|
# XXX
|
|
|
|
eval set -- "$OPTS"
|
|
|
|
ppn = sys.argv[1]
|
|
|
|
while true; do
|
|
|
|
# OPTS=`getopt -o h --long help -- "$@"`
|
|
|
|
case "$1" in
|
|
|
|
# eval set -- "$OPTS"
|
|
|
|
-h|--help) show_help; exit; shift;;
|
|
|
|
# while true; do
|
|
|
|
--) shift; break;;
|
|
|
|
# case "$1" in
|
|
|
|
*) break;;
|
|
|
|
# -h|--help) show_help; exit; shift;;
|
|
|
|
esac
|
|
|
|
# --) shift; break;;
|
|
|
|
done
|
|
|
|
# *) break;;
|
|
|
|
if [ -z "$1" ]; then show_help; exit; fi
|
|
|
|
# esac
|
|
|
|
ppn=$1
|
|
|
|
# done
|
|
|
|
|
|
|
|
# if [ -z "$1" ]; then show_help; exit; fi
|
|
|
|
|
|
|
|
# ppn=$1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# From here, the magic happens
|
|
|
|
# From here, the magic happens
|
|
|
|
self_dir=`dirname $0`
|
|
|
|
# self_dir=`dirname $0`
|
|
|
|
self_dir=`realpath $self_dir`
|
|
|
|
# self_dir=`realpath $self_dir`
|
|
|
|
|
|
|
|
|
|
|
|
make_workspace $ppn $ppn
|
|
|
|
make_workspace(ppn, ppn)
|
|
|
|
$self_dir/run-docker-hub -I PRESENTATION --skip-validation
|
|
|
|
# XXX $self_dir/run-docker-hub -I PRESENTATION --skip-validation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO
|
|
|
|
# TODO
|
|
|
|