Archives mars 2010

Je n'ai pas encore eu le temps de beaucoup chercher, mais je n'ai pas connaissance d'un site web recensant les informations à ce propos, et donc, je vais relayer le mail envoyé il y a une semaine sur plusieurs listes de diffusion, donc la liste perlrdf :

Co-hosted with the annual Geilo seminar of The Norwegian Computer Society we are proud to announce the first International Hacking RDF with Perl Hackathon at Geilo in Norway from the 19th to the 21st of April 2010.

Geilo is a ski resort beautifully situated in the mountains mid-way between Norway's two largest cities Oslo and Bergen, with a train connection to both cities. The annual Geilo seminar has a practical use of Semantic Web track as one of its three tracks, with Greg Williams and Toby Inkster as invited speakers.

The hackathon is organised separately, with these prominent Perl hackers leading the event:

Gregory Todd Williams is the author of RDF::Trine and RDF::Query. He is a Ph.D. student at the Tetherless World Constellation group at the Rensselaer Polytechnic Institute and a prominent member of the SPARQL Working Group, where he is the editor of SPARQL 1.1 Service Description.

Toby Inkster is the author of a large number of RDF-related Perl modules on CPAN: http://search.cpan.org/~tobyink/ , including RDFa parsers, HTML5 microdata parsers, FOAF+SSL authentication modules, etc. He is also a co- inventor of the FOAF+SSL protocol.

Kjetil Kjernsmo is the local organiser, and has been following the RDF world since 1998. He prefers to write in Perl and has a few relevant modules on CPAN. While a member of the Semantic Web Education and Outreach IG, he took the initiative to the Community Projects, that lead to the Linked Open Data project. He has also been a member of the POWDER and SPARQL WGs.

The hackathon will formally convene at 16:00 local time on Monday 19th of April and last until noon Wednesday 21st of April, only interrupted by participants giving talks at the co-located seminar, and we have the possibility of informal chat and hack before that time too.

We will identify a number of subjects that would be interesting to hack on leading up to the event. The discussion will take place on the perlrdf mailing list. To be added to this list, please visit: http://lists.perlrdf.org/listinfo/dev

Beyond accomodation and transportation, there will be a small conference fee, which is currently discussed. Please state your interest to me at kjetil@kjernsmo.net.

Je ne saurai malheureusement pas y participer, mais s'il y a moyen de se joindre au hackathon via le web, je le ferai sans aucun doute !

Il y a quelques temps maintenant, quand j'ai commencé à lire quotidiennement sur mon ebook, j'ai rapidement souhaité être en mesure de lire des articles provenant de web sur ma liseuse. Après un rapide tour d'horizon, je n'avais rien trouvé à l'époque (cela remonte quand même à un petit bout de temps maintenant), et je m'étais donc lancé dans le développement d'une solution personnelle.

Après quelques réflexions, j'ai développé les outils suivants :

  • HTML::Excerpt::FromXPath ; cet outil permet d'extraire une partie d'une page web sur base d'une expression XPath, à cette époque, je n'avais pas encore entendu parlé du merveilleux outil développé par Arc90, j'ai nommé Readability 1
  • Mobigen::Command ; cet outil était juste un wrapper du programme mobigen_linux qui permettait de convertir un fichier HTML en fichier Mobibook ; il est bon de noter que mobigen_linux a été remplacé par kindlegen (disponible gratuitement même si ce n'est pas libre) ;
  • HTML::Image::Save ; cet outil permet de sauvegarder les images d'un fichier HTML, et de modifier ce dernier de manière à faire correspondre les liens des images vers les versions locales ;
  • App::uri2mobi ; est l'outil exploitant ces trois outils précédents dans une interface en ligne de commande.

Par (mauvaise) paresse, je n'ai jamais pris le temps de mettre ces modules sur CPAN 2, mais cela ne m'empêche pas d'en parler quand même.

Donc, dans le cas qui nous occupe aujourd'hui, nous allons voir HTML::Image::Save. L'utilisation de ce dernier est aussi simple que possible :

my $img_saver = HTML::Image::Save->new(
   output_dir => './',
   img_dir => 'images',
);
$img_saver->html( $html );
$img_saver->output_html( 'web_scraping.html' );
$img_saver->save();

Comme le HTML pouvait venir de différents sources (fichiers en local ou récupéré directement sur le web), j'ai préféré la solution la plus simple, à savoir prévoir une méthode pour obtenir le code HTML.

En ce qui concerne le code lui-même, il n'y a pour ainsi que la méthode save() qui est intéressante :

sub save {
    my $self = shift;

    croak "No base URL" unless $self->base_url;
    croak "No HTML" unless $self->html;
    
    my $resolver = HTML::ResolveLink->new(
        base => $self->base_url
    );
    
    my $html = $resolver->resolve($self->html);

    my $tree = HTML::TreeBuilder->new_from_content( $html );
    my @img = $tree->find('img');

    $self->_build_directories();
    
    foreach my $image (@img) {
        my $remote_link = $image->attr('src');
        my $local_link = $self->_get_local_link($remote_link);
        getstore($remote_link, $local_link);
        $image->attr('src', $local_link);
        if ($self->callback) {
            $self->callback->($self, $image, $local_link);
        }
    }

    $self->html($tree->as_HTML());

    if ($self->output_html()) {
        open my $fh, '>', $self->output_html;
        print $fh $self->html();
        close $fh;
    }

    return $self->html();   
}

Cette dernière s'appuie sur HTML::ResolveLink pour modifier le HTML de manière à transformer tout les liens en liens absolus, sur HTML::TreeBuilder pour parcourir les images du code HTML, et enfin sur LWP::Simple pour récupérer les images.

Bref, rien de bien compliqué, et une chouette exploitation du CPAN me permettant d'avoir l'outil qu'il faut, rapidement, et sans trop de prises de tête.

Notes de bas de page:

1 il existe maintenant deux modules permettant de reproduire le comportement de Readability : HTML::ExtractMain et HTML::ExtractContent, donc, dans mes futurs outils, il est plus que probable que j'utiliserai ces derniers.

2 mais je vais le faire, promis !

Perl est une planète

| Aucun Commentaire | Aucun Trackback

Avec un temps de retard, je viens de lire le billet de Jean Véronis intitulé « Ontologies: Perl est une planète du système solaire », (une version anglaise de l'article est disponible).

Et donc, mis-à-part l'intérêt intrinsèque du billet, vive Perl ;-)

En lisant le dernier « PragPub: The First Iteration » (le n°9, disponible sur le site de PragProg), dans l'article « JavaScript: It's Not Just for Browsers Any More » de Jason Huggins, je suis tombé sur une réflexion intéressante :

When we choose a technology to write an application, we don't just choose the language, we also choose the list of available libraries. If a language has many useful libraries with a vibrant community around them, it's going to be easier to write your application in less time.

Bon, dans mon cas, cela m'a fait pensé au Perl et au CPAN, mais je suis sûr que d'autres liront autres choses :)

Pearltrees, RDF & Perl

| Aucun Commentaire | Aucun Trackback

Suite à quelques discussions récentes, je me suis replonger dans les arcanes du RDF. En effet, Pearltrees offrant une possibilité d'exportation des favoris en RDF, ma curiosité naturelle m'a poussée à investiguer de manière à savoir ce que je pouvais faire concrètement avec ce fichier. En plus, @SebDeclercq a été assez gentil que pour me transmettre sa propre sauvegarde, m'épargnant ainsi la tâche fastidieuse d'enrichir mes propres Pearltrees.

Donc, j'ai un fichier contenant plein de liens, et maintenant, je veux exploiter ces informations. Comment faire ? Comme indiqué dans le billet du blog de Nicolas Cynober, nous pouvons utiliser un outil comme SPARQLer pour manipuler les informations. Dans SPARQLer, vous pourrez soumettre votre requête écrite en SPARQL, et obtenir une réponse sous différent format :

  • en XML, avec la possibilité de renseigner un script XSLT permettant de transformer le document (par exemple en XHTML) ;
  • en JSON ;
  • ou encore simplement en texte.

Donc, c'est un outil très intéressant, mais il faut être en ligne, et personnellement, j'aime bien avoir mes outils directement disponibles, quelque soit mes accès au web. Et donc, se pose la question de savoir ce que je peux avoir directement sur ma machine. Un petit tour par le CPAN, et hop, voici quelques modules prometteurs :

  • RDF::Redland ;
  • RDF::Trine ;
  • et celui qu'il me faut pour interroger le fichier via la SPARQL : RDF::Query.

Un petit cpan RDF::Query plus tard, je me retrouve donc avec un module permettant d'interroger en SPARQL un store RDF.

Mais comment faire passer mon fichier pearltrees_export.rdf dans un store RDF ? Relativement simplement, RDF::Trine propose dans son répertoire bin quelques exemples de scripts qui vont nous aider :

  • rdf_init_store.pl qui, comme son nom l'indique, permet d'initialiser un magasin RDF ; j'ai donc lancé la commande suivante pour initialiser ma base de données : ./rdf_init_store.pl sqlite ./pearltrees.db '' '' pearltrees ce qui signifie donc :
    1. initialise une base de données en utilisant SQLite ;
    2. le nom de cette base de données est ./pearltrees.db 1;
    3. le premier '' permet de spécifier le nom d'utilisateur pour la base de données, et il n'y en a pas dans le cas présent ;
    4. le second '' permet de spécifier le mot de passe, idem que précédemment2
    5. et finalement, pearltrees est le nom du modèle de données RDF, ici j'ai arbitrairement donné le nom de pearltrees ;
    6. la commande une fois lancée me donne un message d'avertissement : Log4perl: Seems like no initialization happened. Forgot to call init()?, mais quand je vérifie via un sqlite3 pearltrees.db, je constate que les tables (Bnodes, Literals, Models, Resources et Statement2742456113224982524) ont bien été créées, donc, pas de soucis !
  • rdf_store_add_file.pl qui permet d'ajouter un fichier dans la base de données de triplets ; ce script s'utilise de la manière suivante ./rdf_store_add_file.pl sqlite ./pearltrees.db '' '' pearltrees sebdeclercq.rdf, ce qui suit la logique du script précédent (utilisation de SQLite, le nom de la base de données, le nom d'utilisateur, le mot de passe et le nom du modèle de données RDF.

Sur mon EeePC 1005HA, voici quelques statistiques :

  • pour un fichier RDF de 421515 octets, j'obtiens une base de données de 1872896 octets ;
  • le traitement du fichier prend un peu de temps, voici le résultat de time :
real    16m52.234s
user    3m33.573s
sys     0m17.757s

Après l'exécution de rdf_store_add_file.pl, nous nous retrouvons donc avec une base de données qui pourra servir de base à RDF::Query.

Voici un petit script illustrant l'utilisation de RDF::Query :

#!/usr/bin/env perl

use strict;
use warnings;

use RDF::Trine;
use RDF::Trine::Store::DBI;
use RDF::Query;
use Data::Dump;

my $sparql = <<'SPARQL';
PREFIX pt: <http://www.pearltrees.com/rdf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT ?title ?url
WHERE {
   ?pearl rdf:type pt:pearl;
          dc:title ?title;
          owl:sameAs ?url;
          pt:parentTree ?tree
}
ORDER BY DESC (?tree)
SPARQL

my $store =
  RDF::Trine::Store::DBI->new( 'pearltrees', 'DBI:SQLite:dbname=./pearltrees.db', '', '' );
my $model = RDF::Trine::Model->new($store);

my $querier = RDF::Query->new($sparql);

my $iterator = $querier->execute($model);
while ( my $row = $iterator->next ) {
    print $row->{title} . ' ' . $row->{url} . "\n";
}

Voilà pour aujourd'hui. Je suis en train de travailler sur un script s'appuyant sur HTTP::Server::Simple et Template::Declare afin d'avoir une interface plus agréable pour tester mes requêtes SPARQL.

Keep in touch…

Notes de bas de page:

1 puisque nous utilisons SQLite, la base de données est en fait un fichier

2 dans le cas d'une base de données MySQL, cela aurait été nécessaire évidemment

À propos de cette archive

Cette page est une archive des notes de mars 2010 listées de la plus récente à la plus ancienne.

février 2010 est l'archive précédente.

avril 2010 est l'archive suivante.

Retrouvez le contenu récent sur l'index principal ou allez dans les archives pour retrouver tout le contenu.

Pages

Powered by Movable Type 4.261