mardi 13 décembre 2011

Séance #7 - application (1)

Pour pouvoir faire une analyse linguistique pertinente sur le mot qu'on a choisi pour notre projet, il est nécessaire de l'extraire des pages web récupérées avec son contexte.
La première solution que nous avons utilisée pour cette étape est d'inclure à notre script le programme minigrep qui nous a été fourni.

Pour cela, rien de plus "simple", il "suffit" d'ajouter quelques lignes de code dans notre script. Où? Eh bien, puisqu'il s'agit d'extraire un contexte textuel et qu'on veut toujours travailler en utf-8, il faut se situer juste après les commandes lynx (dump) ou, éventuellement, après les commandes iconv (conversions éventuelles si le fichier original n'était pas en utf-8), et là, on tape:
  • perl [chemin relatif vers le programme]  "UTF-8" [chemin relatif vers le fichier cible] [chemin relatif vers le motif à extraire] ;
Bien évidemment, cette commande suppose que l'on a bien téléchargé le programme minigrep multilingue, et qu'on a créé un fichier txt contenant le motif recherché sur le même modèle que celui donné lors du téléchargement de minigrep (c'est-à-dire, MOTIF=regexp).
  • mv resultat-extraction.html ./CONTEXTES/$i/$j-minigrep.html ;
Petit rappel: mv (move) est une commande très utile qui permet de déplacer un fichier, et/ou bien de le renommer (le processus étant en réalité le même...). Ici, la commande renomme ET déplace le résultat de l'extraction faite par minigrep.
L'utilité de cette ligne? Tout simplement de stocker le résultat pour pouvoir y accéder dans le tableau, ce qui ne serait pas possible autrement... En effet, l'output de minigrep est spécifié à l'intérieur même du script et ne peut donc pas comporter dans son chemin les variables $i et $j issus du script bash et dont on se sert pour spécifier les noms de fichiers dans lesquels on stocke les informations liées aux différents urls. Propos testés et approuvés.

/!\ Problème lors de l'exécution du programme minigrep:
Il est possible de tomber sur une erreur qui commence par "Can't locate Unicode/String.pm in @INC" qui signifie qu'il manque des paquets à perl pour exécuter le programme minigrep, ou encore "ERROR: Can't create '/usr/local/lib/perl/5.12.4/Unicode' mkdir /usr/local/lib/perl: Permission non accordée at /usr/share/perl/5.12/ExtUtils/Install.pm line 494", autre problème dû au fait qu'installer un programme ou modifier le paramétrage du système doit être fait à travers le compte administrateur (cf. sudo). Ce problème a été réglé avec la commande suivante: sudo perl -MCPAN -e 'install Unicode::String'.

Tout cela nous donne le tableau suivant:
Si on clique sur les liens vers les résultats de l'extraction par minigrep, on se rend compte que parfois, tout marche très bien...

... et parfois beaucoup moins.
Dans le dernier fichier, on remarque que le motif a été trouvé dans des balises html et des urls, ce qui n'est pas pertinent pour notre projet. Next: améliorer l'expression régulière du motif?

mardi 29 novembre 2011

Séance #6 - application

Un aspect important n'avait jusqu'ici pas été pris en compte dans nos scripts: l'encodage de la page html. Dans ce projet, nous sommes amenées à travailler sur plusieurs langues comportant des caractères non-ascii et il est donc capital de pouvoir toutes les traiter sans avoir à spécifier une table de caractères différente à chaque fois. Cette possibilité nous est donnée par utf-8.
Convertir un fichier en utf-8 n'est pas compliqué en soi, mais cette étape en implique bien d'autres puisqu'il faut d'abord savoir de quel encodage on part avant d'appliquer le processus de conversion!

 Avant même d'écrire du code, commençons par structurer nos idées. Voici ma démarche détaillée en bon (?) français:
Si l'encodage repéré par file est bien utf-8,
... alors on dumpe directement - lynx
... sinon, on cherche à savoir si l'encodage repéré est connu d'iconv
      Si l'encodage est connu d'iconv
      ... alors convertir puis dumper - iconv, lynx
      ... sinon, s'aider des métadonnées html
         Si l'argument charset de la balise meta est bien présente,
         ... alors extraire la valeur de l'argument charset
            Si l'encodage extrait est connu d'iconv,
            ... alors convertir puis dumper - iconv, lynx
            ... sinon, échec: encodage extrait inconnu d'iconv.
         ... sinon, échec: encodage non précisé dans le code html.

Ce qui donne en script:


 Pour réaliser toutes les étapes décrites ci-dessus, nous nous sommes servies des commandes file, iconv, egrep et lynx que nous détaillons ci-dessous:
  •  encodage=`file -b --mime-encoding ./PAGES-ASPIREES/$i/$j.html`; (qui précède toutes les étapes et n'apparaît pas dans les screenshots)
Cette commande permet de stocker dans la variable encodage le résultat de la commande file qui, elle, nous donne l'encodage de la page mise en input.
-b (brief) est une option qui rend un output bref, c'est-à-dire sans le nom du fichier. (./PAGES-ASPIREES/1/1.html: text/html; charset=utf-8)
--mime-encoding est une option qui nous donne l'encodage de page sans le type de contenu et sans le nom des arguments. (text/html; charset=utf-8).
[... et voilà comment se débarrasser des cuts.]
  • verif_iconv=`iconv -l | egrep -io $encodage`;
La première partie de cette commande nous fournit la liste des encodages connus par la commande de conversion iconv grâce à l'option -l (list). L'output de cette partie est redirigé vers l'input de la seconde partie qui va l'utiliser en contexte. En effet, la commande egrep s'utilise avec la syntaxe suivante: egrep [options] "motif" "contexte/domaine de recherche". Ici, le motif est l'encodage repéré au préalable par file, et les options utilisées, -i (ignore-case) et -o (only-matching) permet de ne pas prendre en compte la casse (ne sait-on jamais...) et de ne récupérer que ce les caractères qui correspondent à ce que l'on cherche.
  • lynx -dump -nolist -display_charset=$encodage ./PAGES-ASPIREES/$i/$j.html > ./DUMP-TEXT/$i/$j.txt;
La commande lynx a déjà été expliquée dans l'article précédent. Nous y avons juste ajouté l'option -display_charset qui indique à lynx dans quel encodage il faut écrire l'output de la commande.
  • iconv -f $encodage -t utf-8 "./PAGES-ASPIREES/$i/$j.html" > "./DUMP-TEXT/$i/$j-utf8.txt";
Si l'encodage repéré par file ou dans les métadonnées html est connu de la commande iconv, on peut appliquer cette ligne de commande qui va convertir le fichier à partir d'un encodage donné (-f (from code)) à un autre (-t (to code)).
  • egrep -qi ".*charset ?=.*" ./PAGES-ASPIREES/$i/$j.html
L'option -q (quiet) permet de ne rien écrire dans le terminal et de ne rien garder en output si le motif n'est pas trouvé dans le contexte. Le motif se décompose de cette manière: "trouver la chaîne de caractères charset, précédée de n'importe quoi (.* n'importe quel caractère à l'infini) et suivie ou non d'un espace ( ?) puis d'un = lui-même suivi de n'importe quel caractère".
  • charset_line=$(egrep -m 1 "charset=.*\"" ./PAGES-ASPIREES/1/31.html);
L'option -m (max count) suivi d'un chiffre permet de spécifier le nombre de correspondance que l'on veut, arrêtant le programme dès que ce nombre est atteint.
  • charset=$(expr "$charset_line" : '.*=\(.*\)\"');

La commande expr permet d'évaluer les expressions, et ici d'utiliser les parenthèses qui extraient directement le motif qui sont incluses dedans. Cette expression régulière illisible et qui nous a donné du fil à retordre se lit donc: "extraire tous les caractères quels qu'ils soient (.*) entre les parenthèses échappées par \ qui sont précédées d'un = lui-même précédé de n'importe quel caractère (.*), et suivies d'un " (échappé aussi par \). [on se comprend, n'est-ce pas?]

Ce qui donne le résultat suivant:


mercredi 23 novembre 2011

Séance #5 - applications


Nouvelle séance, nouvelle étape du projet, nouvelle colonne!

Puisque notre but final est de travailler sur du texte, il est plus pratique d'avoir comme support un fichier texte, plutôt qu'une page html. Pour passer de l'un à l'autre, nous n'avons besoin que d'un élément: lynx, un navigateur web, qui, comme tous les autres navigateurs, permet d'accéder à des sites web, mais qui a la particularité de le faire en mode textuel uniquement, et donc par l'intermédiaire unique du clavier.
/!\ Il n'est pas installé automatiquement sur Ubuntu, il convient donc de l'installer rapidement avant de l'utiliser...

La ligne de commande essentielle que nous avons alors ajoutée est celle-ci:
lynx -dump -nolist $nom > ./DUMP-TEXT/$i/$j.txt;
Plusieurs points importants:
  • La situation: cette instruction est située à l'intérieur des deux boucles du script actuel (d'abord celle qui génère les tableaux, puis celle qui génèrent les lignes). En effet, elle doit s'appliquer à toutes les URLs de toutes les langues sur lesquelles on travaille.
  • Les options: -dump permet de ne récupérer que le contenu textuel de la page lue par lynx; -nolist permet quant à lui de ne pas récupérer les liens hypertext.
  • La redirection de flux sortant (>): nécessaire si on veut éviter que le terminal ne surchauffe l'ordinateur en se remplissant de tout le contenu textuel de toutes les URLs traitées, elle redirige le tout dans un fichier qui sera créé à l'occasion.
 Script:

(Début du) tableau généré



Quelques petites modifications du script ont également été apportées, notamment pour créer les dossiers qui doivent contenir les fichiers textes "dumpés" (mkdir ./DUMP-TEXT/$i;) ainsi que pour créer la colonne du tableau qui permet d'y accéder.

Efficacité des commandes utilisées?
Chose importante: il a d'abord fallu, cette semaine, remplacer les liens renvoyant à des pages qui ne pouvaient pas être aspirées par la commande curl (voir post précédent), et ce, à cause d'accès refusés par les serveurs en question. Résultat: et rebelote pour la recherche d'URLs contenant le mot "rêve"! [Et on maudit la cnn et le new york times.]
... et ce n'est pas fini. Il semblerait que même si la page a été aspirée avec succès par curl, il soit possible que le problème des accès se re-pose pour lynx:

Page "dumpée" par toutes les pages du telegraph:
 Malédiction? Acharnement? Complot?

mardi 15 novembre 2011

(Mises) à jour

Avec un tel titre, vous vous demandez sûrement...
...si l'on a finalement réussi à récupérer 50 URLs dans les 4 langues dans lesquelles on comptait travailler? 
...Ou si l'on a fini tous les exercices demandés depuis le début du projet?! 
...Ou encore si l'on a enfin assimilé toutes les notions apprises en cours?!! 
Eh bien oui, oui et oui! ...mais ce n'est pas le sujet. En réalité, pour une navigation plus efficace et agréable, notre blog a été mis à jour!

Au menu (de droite):
  • Suppression de la rubrique "membres" (btw, à quoi elle pouvait servir...?)
  • Ajout d'une fonction recherche au sein du blog! Plus besoin de galérer avec CTRL+F -ou CMD-F pour les chanceux- à travers toutes les pages [certes peu nombreuses pour le moment...] du blog.
  • Ajout de libellés sur les billets, et de la rubrique correspondante: le sujet de chaque billet est maintenant plus clair, et il est désormais possible de trouver tous les billets concernant le langage bash en 1 clic!

Si tout ça vous inspire, vous pouvez faire de même sur votre blog en allant tout simplement dans la partie "Mise en page" du menu "Conception" -du moins si vous êtes également hébergés par blogger. 
A noter qu'il est également très facile de sauvegarder toutes vos modifications en cliquant sur "Sauvegarde/Restauration" (menu "Modèle"), puis de jouer avec les modèles et les paramètres de personnalisation du blog, puis de restaurer avec la même touche si jamais vos délires vous ont portés trop loin! [hem...]

En résumé: vous pouvez maintenant naviguer dans ce blog en suivant le cours -inverse- du temps, en faisant des bonds dans le temps (rubrique "Archives"), ou encore en utilisant un mot-clé (rubrique "Libellés" ou "Recherche"). 

C'est pas beau tout ça? :)

PS: petite précision qui peut être utile, dans le post sur les applications de la séance #3 j'ai ajouté la solution à mon problème d'encodage et de décodage des caractères non-ASCII en utf-8.

Séance #4 - applications


Lors du cours du 9 novembre, nous avons appris de nouveaux outils tels que wget ou curl qui vont nous permettre de passer à une étape supérieure de notre projet: l'aspiration de pages web.
Notre but est maintenant d'écrire un script qui exécute plusieurs tâches:
1- Aspirer les pages web correspondant aux urls que nous avons trouvées
2- Ranger les pages aspirées dans des répertoires correspondant à chaque langue, sous le répertoire "PAGES-APSIREES", dans l'arborescence de travail.
3- Constituer une page html qui présente un tableau par langue, contenant des colonnes qui correspondent respectivement au numéro de l'url pour la première colonne, au nom de l'url avec un lien vers la page web correspondante pour la seconde, au lien vers la page aspirée de cette url pour la troisième, puis au retour de la commande curl (0 si opération réussie, un autre chiffre si opération échouée) pour la dernière.

N'ayant pas de résultat pour la commande wget sur mac, (lorsque j'effectue la commande  "man wget" sur  le terminal, j'obtiens la réponse "No manual entry for wget"), nous avons rédigé le script avec la commande curl pour aspirer les pages web correspondant aux urls que nous avons trouvées pour notre projet autour du mot "rêve".
Voici le résultat dans l'arborescence de travail:

Voyons maintenant les résultats dans la page html générée par le script (sachant que les 3 tableaux apparaissaient bel et bien sur une même page html, mais que nous avons séparés pour plus de clarté).




Nous observons que les trois* tableaux ont bien été générés et présentent bien, en troisième colonne, le lien vers la page aspirée des urls, ainsi que leur résultat noté "0", en quatrième colonne indiquant que tout -ou presque!- s'est bien déroulé.
Si l'on observe cette ligne de résultat dans notre tableau html: 

Nous constatons, pour l'URL 49 que curl a détecté une erreur de type 56. Si l'on regarde dans le manuel d'erreur http://curl.haxx.se/docs/manpage.html, on trouve cette explication: Failure in receiving network data, décrivant un problème qui a eu lieu lors de l'envoi des données entre le serveur du site et notre machine. Il semblerait que ce problème ne soit pas de notre ressort, alors la meilleure solution que nous avons trouvée est... de changer d'url!

*en attendant les urls en coréen, si Ilaine s'en sort...!

mercredi 9 novembre 2011

Séance #3 - applications

Parées de toutes les commandes que nous avions apprises jusqu'ici, nous voici en direction de notre premier exercice du projet: la création d'un tableau regroupant les URLs récupérées.

Cet exercice consiste à améliorer le script d'origine étudié en cours et se compose de plusieurs étapes:
A] Insérer une nouvelle colonne pour constituer une colonne de numérotation des URLs.
B] Établir un lien vers les pages de chacune de nos URLs.
C] Modifier le script pour traiter plusieurs fichiers d'URLs et pour construire en sortie plusieurs tableaux dans le même fichier.
 A] Numérotation des URLs
Concrètement, numéroter les URLs, ça veut dire écrire "1" dans la première cellule de la première ligne, à côté de la première URL, puis écrire "2" dans la première cellule de la deuxième ligne, à côté de la deuxième URL etc. Bref, un exercice manuel beaucoup trop fastidieux mais, heureusement pour nous, facilement automatisé en trois étapes:
  1. Créer une variable qui contiendra les chiffres servant à la numérotation: i=1;
  2. Créer une cellule à chaque ligne: <tr><td>$i</td><td>$nom</td></tr>
  3. Incrémenter la variable dans la boucle déjà établie: i=`expr $i + 1`; (dans la boucle for)
Si les deux premières étapes découlent naturellement du cours, ce n'est pas le cas pour la troisième, qui, elle, a nécessité quelques recherches sur internet. En effet, après avoir essayé diverses méthodes connues (incrémentation par i++ ou encore i=i+1 ou i=$i+1) dont aucune ne fonctionnait, nous nous sommes résignées à nous documenter. La commande expr que nous avons trouvée sert en réalité à évaluer des expressions, ici arithmétique puisque l'incrémentation est une addition avec pour deuxième argument 1. La valeur de l'évaluation est alors retournée et assignée à la variable i grâce aux antiquotes ``.


B] Liens hypertexte
Pour cet étape, il s'agit de ne pas afficher uniquement les urls, mais d'en faire des liens hypertextes cliquables qui vont directement aux pages indiquées par les urls. On utilise pour cela la balise HTML <a href "url.html">url.html</a>.


C] Modification du script pour traiter plusieurs fichiers d'URLS
La solution que nous avons adoptée est la suivante:
  1. Créer une deuxième variable qui va contenir le lien vers le deuxième fichier
  2. Créer une deuxième boucle for pour générer automatiquement un deuxième tableau sur le modèle du premier.
Voici élaboré pour cet exercice, ainsi que son résultat.

Problème: si cette méthode fonctionne pour deux fichiers d'URLs, elle ne permet cependant pas de traiter moins de deux fichiers, ou plus. Voici donc le script retravaillé après avoir vu la correction mise en ligne, suivi de la page html générée par ce script: 
 
Avec l'assignation du chemin vers le répertoire contenant les URLs à la variable et avec la création d'une boucle générant un tableau entier, dans laquelle on a laissé celle qui génère chaque ligne des tableaux, il est maintenant possible de traiter autant de fichiers qu'il est nécessaire.

/!\ Le codage de la page html a été ajusté manuellement, le ° étant un caractère posant le même problème que les accents dans un des articles précédents.

EDIT: problème d'encodage et de décodage réglé! Il faut juste vérifier systématiquement que l'on a bien à la fois un script écrit en utf-8 (soit en vérifiant avec "Enregistrer sous", soit en convertissant le fichier avec la commande iconv) ET la balise <meta /> correctement copiée tapée qui précise au navigateur qu'il est judicieux de lire la page en utf-8. La première condition est inutile sans la seconde, et vice-versa...!

lundi 7 novembre 2011

Séance #3 - création d'un tableau de liens

Lors de la troisième séance de cours, nous avons officiellement terminé la phase introductive à UNIX pour nous consacrer -enfin?- à notre projet.

Phase 1: construction progressive de la chaîne de traitement. 
Phase 2: des nuages et des arbres de mots

Premier script: créer un tableau de liens.

 Voici le script étudié en cours auquel nous avons ajouté des commentaires:

Nous avons donc appris, durant cette séance, à créer un tableau de liens en utilisant les éléments suivants:
  • read [variable]: cette commande permet de déclarer une variable à laquelle on assignera une valeur de manière interactive.
  • for [variable] in [list]: cette commande crée une boucle for telle que "pour tout élément de [list] provisoirement stocké dans [variable] , exécuter les instructions suivantes". Le couple do / done sous Unix correspond aux { } sous mac et cygwin, et permettent de délimiter les instructions que l'on veut répéter selon la boucle.
    • do [instructions] done
    • { [instructions] }
  • for var1 in `cat $var2`: la commande cat donne la liste des éléments de la variable qui suit. Les antiquote `` entourant cette commande permettent ici de récupérer son résultat et de l'intégrer dans la commande for [variable] in [list] en tant que [list].
 /!\ si var est une variable, alors $var donne accès à la valeur qui est stockée dans l'espace de mémoire affectée  à la variable.

Et voilà pour le cours! Prochaine étape: l'application de la séance #3.