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_linuxqui permettait de convertir un fichier HTML en fichier Mobibook ; il est bon de noter quemobigen_linuxa été remplacé parkindlegen(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 !

Commentaires récents