Récupération des ids et urls des ressources

On utilise comme dans un billet précédent la méthode searchXMLDocs du module ori-oai-indexing.
On récupère l’identifiant directement depuis un dictionnaire.
Pour l’url on s’impose le fait de résoudre un XPath en Python -> on aurait aussi pu plus simplement utiliser la méthode searchFromAttributes qui à priori peut nous renvoyer directement l’id et l’url par exemple (cf IndexingServiceInterface.java).

Pour l’appel du Web Service SOAP, on continue bien évidemment avec SOAPpy.
Pour la résolution du Xpath, on choisit libxml2, le binding python de la librairie C.
=> sous debian :
apt-get install python-libxml2

Voici les 2 méthodes qui implémentent ces 2 aspects (l’une appelant l’autre) :

def getUrlsIdsFromOriIndexing():

    urls_ids = []

    WSDLFILE = ’http://ori-oai-indexing.univ-rennes1.fr/indexing/xfire/IndexingService?WSDL’
    oriindexing = WSDL.Proxy(WSDLFILE)
    request = ’md-ori-oai-namespace:("http://ltsc.ieee.org/xsd/LOM")’

    results = oriindexing.searchXMLDocs(request, 1, 5)[’results’][’SearchResult’]
    for result in results:
        if result[’id’] != None and result[’noticeContent’]!= None:
            ide = result[’id’]
            url = getUrl(result[’noticeContent’].encode(’utf-8’))
            urls_ids.append((ide, url))
    return urls_ids

   
   
def getUrl(lomXml):
    doc = libxml2.parseDoc(lomXml)
    ctxt = doc.xpathNewContext()
    ctxt.xpathRegisterNs(’lom’, ’http://ltsc.ieee.org/xsd/LOM’)
    res = ctxt.xpathEval("//lom:technical/lom:location")
    return res[0].get_content()



Notez que l’on a ici volontairement positionné le lastNotice de la méthode
searchXMLDocs à 5 pour tester plus facilement.
Notez également l’utilisation des espaces de noms (namespaces) au travers de libxml2 :
  • on définit un binding préfixe / espace de noms : ctxt.xpathRegisterNs('lom', 'http://ltsc.ieee.org/xsd/LOM')
  • on utilise ce binding dans la résolution d’un XPath : ctxt.xpathEval("//lom:technical/lom:location")
Voici ce que donne l’appel de la méthode getUrlsIdsFromOriIndexing() dans une console python (le fichier python étant shot.py):

>>> import shot
>>> shot.getUrlsIdsFromOriIndexing()
[(’rennes1-ori-wf-1-295’, ’http://www.med.univ-rennes1.fr/wkf/stock/RENNES20071019121406burgunsondages08.pdf’), (’rennes1-ori-wf-1-289’, ’http://www.med.univ-rennes1.fr/wkf/stock/RENNES20061221025012lepogampLA_FONCTION_RENALE.doc’), (’rennes1-ori-wf-1-285’, ’http://www.med.univ-rennes1.fr/wkf/stock/RENNES20060915113249tbuiPoly_SEmio_2006.pdf’), (’rennes1-ori-wf-1-283’, ’http://www.med.univ-rennes1.fr/wkf/stock/RENNES20060613052202duvauferBases_en_radioanatomie_1.ppt’), (’rennes1-ori-wf-1-287’, ’http://www.med.univ-rennes1.fr/wkf/stock/RENNES20061213113922deugnierAnatomoPhysioFoie.doc’)]
>>>


Stratégie de Captures ...

On l’a évoqué en introduction, browsershots est une solution relativement complète pour faire des captures d’écran des ressources webs : il permet d’utiliser des postes clients distants pour réaliser les captures : les postes clients étant +/- "pilotés" par le serveur.
Pratique, mais un serveur ne suffit pas, il faut des postes clients, cela peut être lourd à mettre en place surtout dans une première phase de mise en place de captures sur un nombre de ressources relativement limités ...

Aussi l’idée ici est de n’utiliser que le serveur lui-même, qui plus est, n’a pas de serveur X. On ne souhaite pas installer sur le serveur une interface graphique Gnome ou autre.

Une "capture d’écran" étant une image, on a théroiquement 2 "possibilités" :
* faire vraiment une capture d’écran d’un client X interprétant la ressource numérique (html, pdf, flash, ppt ...)
* transformer/convertir la ressource en une image.

En fait suivant les cas, on choisira la méthode la plus simple selon le format donné.
=>
  • pour html/flash, il parait plus simple d’utiliser un navigateur comme firefox et de faire une copie d’écran.
  • pour le pdf, on pourrait utiliser un plugin dans le navigateur, mais on n’a pas forcément envie d’installer ce genre de chose ... d’autant que ghostscript, outil libre, peut par exemple nous convertir une page pdf complète en une image via une ligne de commande.
  • pour les autres formats, je vous laisse y réfléchir et donner des idées en commentaires si vous le souhaitez ;-) [openoffice.org ? pptview ? etc.]

Mise en place des Captures ...

Firefox

Il faut installer Firefox sur le serveur, mais pour qu’il puisse tourner, il faut aussi installer un serveur X virtuel que l’on démarrera lorsqu’on aura besoin de Firefox simplement : Xvfb par exemple.

On démarrera Firefox comme cela :

Xvfb :1 -screen 0 1280x960x24&
firefox --display=:1 http://www.univ-rennes1.fr

Pour la capture on peut utiliser import par exemple fourni avec imagemagick, d’autant qu’une fois la capture faite, imagemagick pourra nous servir également pour retravailler nos images à souhait : en faire des vignettes (thumbnail), y mettre un effet shadow (ombre), etc.

Un des soucis  que l’on peut rencontrer avec Firefox cependant est que la taille de la fenêtre de firefox ne s’ouvrira pas forcément en grand ... dans certaines versions on a l’option -fullscreen de disponible mais pas dans toutes.

Un certain nombre d’extensions firefox peuvent résoudre habilement ce problème, on peut utiliser :

conjointement.
Le problème est : comment installer une extension Firefox sur un serveur qui ne contient pas d’X ? -> pas de possibilité de cliquer dans une boîte de dialogue ou autre ....

Une solution simple : installer les extensions sur un firefox sur un poste en local sous un profil donné (bénéficant d’une interface graphique), en profiter pour configurer le firefox comme on le souhaite (on peut ajouter des extensions aussi pour supporter d’autres formats par exemple ... d’ailleurs si vous avez des idées, n’hésitez pas à nous les donner dans les commentaires ;-) ), puis copier coller le profil ainsi créé (voir le répertoire .mozilla/firefox) sur le serveur (on spécifie l’utilisation de ce profil par défaut dans .mozilla/firefox/profiles.ini) ... le tour est joué !

Ghostscript

Il faut l’installer (apt-get) et voir ses nombreuses possibilités, par exemple :

gs -dNOPAUSE -sDEVICE=png256 -q -dBATCH -sOutputFile=test.png test.pdf

Imagemagick

De même, installez le (apt-get toujours si vous êtes sur debian :-) ) et voyez toutes ses possibilités !

Le script ... !

Ici pour tout ce "bricolage" on va faire un petit script python, qui
  • va récupérer les urls et ids depuis l’indexing
    => cf plus haut : SOAPpy + libxml2
  • va regarder si le format du fichier derrière l’url correspond à html ou un pdf
    => librairie urllib2
  • va appeler les programmes xvfb, firefox, ghostscript, imagemagick qui vont bien.
    => librairie os
=> Le script complet est affiché ici et est également en fichier attaché à ce billet.


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import time
from SOAPpy import WSDL
import libxml2
import urllib


def closeFirefox():
    os.system('killall -3 firefox')
    os.system('killall -9 firefox-bin')

def closeXvfb():
    os.system('killall -9 Xvfb')


def initXvfb():
    psXvfb = os.popen('ps -edf | grep Xvfb').readlines()
    if len(psXvfb) < 3:
        os.system('Xvfb :1 -screen 0 1280x960x24&')
        #os.system('Xvfb :1 -screen 0 1024x768x24&')
        time.sleep(3)

def launchFirefox(url):
    psFirefox = os.popen('ps -edf | grep firefox').readlines()
    if len(psFirefox) < 3:
        print '##### open url ... :' + url
        os.system('firefox --display=:1 ' + url + ' &')
        #wid = os.popen('DISPLAY=:1 wmctrl -lp | grep firefox | cut -f1 -d\ ').readlines[0]
        #print wid
        #os.popen('DISPLAY=:1 wmctrl -i -r ' + wid + ' -b toggle,fullscreen,above')
        time.sleep(3)


def shot(name, url):

    try:
        url_open = urllib.urlopen(url)
        infos = url_open.info()
        typ = infos.gettype()

        if url_open.geturl()[:5] != 'https':
            typ = typ
            if typ == 'text/html':
                # os.system('DISPLAY=:1 firefox -remote "openurl(' + url + ')"')
                launchFirefox(url)
                time.sleep(10)
                os.system('DISPLAY=:1 import -window root ' + name + '.png')
                closeFirefox()
            if typ == 'application/pdf':
                urllib.urlretrieve(url,name)
                os.system('gs -dNOPAUSE -sDEVICE=png256 -q -dBATCH -sOutputFile=' + name +'.png ' + name)

            time.sleep(1)
    except:
        print 'error ...'


def thumb(img):
    os.system('cp ' + img +'.png ' + 'thumb-' + img +'.png ')
    os.system('mogrify -thumbnail 100 thumb-' + img +'.png')

def thumb300(img):
    os.system('cp ' + img +'.png ' + 'thumb300-' + img +'.png ')
    os.system('mogrify -thumbnail 300 thumb300-' + img +'.png')

def vignette(img):
    os.system('convert ' + 'thumb-' + img + '.png -bordercolor grey60 -border 1 -background  black \( +clone -shadow 60x4+4+4 \) +swap -background  none -flatten -depth 8 ' + 'vign-thumb-' + img + '.png')



def getUrlsIdsFromOriIndexing():

    urls_ids = []

    WSDLFILE = 'http://localhost:6380/ori-oai-indexing/xfire/IndexingService?wsdl'
    oriindexing = WSDL.Proxy(WSDLFILE)
    request = 'md-ori-oai-namespace:("http://ltsc.ieee.org/xsd/LOM")'

    results = oriindexing.searchXMLDocs(request, 1, 5)['results']['SearchResult']
    for result in results:
        if result['id'] != None and result['noticeContent']!= None:
            ide = result['id']
            url = getUrl(result['noticeContent'].encode('utf-8'))
            urls_ids.append((ide, url))
    return urls_ids

   
   
def getUrl(lomXml):
    doc = libxml2.parseDoc(lomXml)
    ctxt = doc.xpathNewContext()
    ctxt.xpathRegisterNs('lom', 'http://ltsc.ieee.org/xsd/LOM')
    res = ctxt.xpathEval("//lom:technical/lom:location")
    return res[0].get_content()
   

closeXvfb()
closeFirefox()
initXvfb()
print 'init Xvfb ok ...'
for (id, url) in getUrlsIdsFromOriIndexing():
    url = url.replace('https','http')
    print url + "  ... : " + id
    shot(id, url)
    thumb300(id)
    thumb(id)
    vignette(id)
closeXvfb()
print 'close Xvfb ok ...'



On notera cependant que
  • on relance firefox pour chaque capture plutôt que de rouvrir une page dans le même onglet principal (cela afin d’éviter de  rester sur une boîte de dialogue quelconque; javascript [qu’on désactivera cependant peut-être], certificat ssl non valide, etc.
  • on tente pour les accès https, de voir si vraiment on ne peut pas atteindre l’url en http
  • on choisit de ne pas faire de captures des pages en https
  • etc.

Utilisation dans ori-oai-search ...

Ensuite, dans le cadre d’ori-oai, et parcequ’on a soigneusement nommé nos images via l’identifiant de chaque notice, on peut facilement modifier directement la page jsp des résultats d’ori-oai-search pour intégrer ces captures.
voici alors ce que vous poiuvez obtenir :