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.

Séance #2 - applications

Après la séance #2 sur l'introduction à UNIX, nous devions appliquer les éléments appris en cours sous la forme de deux exercices que voici:

A] Écrire un script (dans le dossier PROGRAMMES) permettant de générer dans le répertoire DUMP-TEXT un fichier txt contenant 2 lignes (sur la première, votre nom, sur la seconde, le mot choisi pour votre projet).


Screenshot du script:
Screenshot du fichier txt:
Ce premier exercice ne pose pas de problèmes majeurs puisqu'il est l'application directe du cours avec l'utilisation de la commande echo et de la redirection de flux sortant (">" et ">>") expliqués dans les commentaires du script.
En revanche, ce qui a bien failli nous empêcher de dormir, ce sont... les fautes faites en tapant le chemin (erreur sur le nom d'un répertoire, erreur sur le choix du répertoire destinataire, inattention quant à la casse...) du fichier de sortie. Moralité: 
Si l'être humain tient à sa crinière,
Fût-il ingénieux, sensé, brillant,
Qu'il apprenne que les mécanismes sont plus fiables et constants
A naviguer dans des méandres divagants,
Qu'un esprit capricieux, entêté et fier!
...ou pour éviter l'arrachage frénétique de cheveux, ça vaut le coup d'utiliser la touche TAB qui permet de compléter automatiquement les chemins, bout par bout, à partir de quelques lettres.

B] Écrire un script (dans le dossier PROGRAMMES) permettant de générer dans le répertoire TABLEAUX un fichier html contenant 1 tableau avec 2 lignes (sur la première, votre nom, sur la deuxième, le mot choisi pour votre projet).


Screenshot du script:
Screenshot de la page html:
Il s'agit cette fois non pas de produire un fichier texte, mais une page html, c'est-à-dire une page écrite dans un langage qui a sa propre syntaxe et qu'il faut adapter à bash, notamment en déspécifiant les double quote " " (utilisées pour donner des valeurs aux arguments des balises html) grâce à l'utilisation d'antislash \ antéposés (cf. screenshot du script).
A noter que contrairement à la correction, nous n'avons utilisé qu'une seule fois la commande echo et que nous avons donc regroupé tout le code html en une fois, avec même des sauts de ligne et... ça fonctionne!

Nous avons bien fait attention à encoder notre script en utf-8, à le spécifier dans une balise meta dans l'en-tête du code html, et même vérifier l'encodage avec la commande file puis reconverti le sript en utf-8 avec la commande iconv pour être définitivement sûr de l'encodage, pas moyen d'afficher l'accent circonflexe du mot "rêve"! Faute de trouver une solution, nous avons choisi ici de ne pas utiliser d'accent.

mardi 1 novembre 2011

Premiers pas vers le site...

... avec l'introduction au langage HTML.

Lors de notre troisième séance de cours de "programmation et projet encadré", on nous a introduit au langage HTML, langage que l'on utilisera ensuite pour créer notre site.

Voici le code de l'exercice qui nous a été demandé:


Il s'agissait de créer une page HTML minimale, avec les sections structurelles indispensables head et body et d'y mettre un simple petit message et un tableau. Pour se faire, il a fallu utiliser les balises suivantes:

  • <html></html>: la plus importante et la première balise à mettre parce que toute page html contient cette balise et qu'elle englobe tout!
  • <head></head>: balise structurelle où l'on met des informations non-visibles au visiteur.
  • <title></title>: balise contenue dans l'en-tête head et qui elle-même contient le titre de la page.
  • <body></body>: balise structurelle où l'on met le contenu visible d'une page.
  • <p></p> (paragraph): balise permettant d'écrire un paragraphe de texte (avec saut et retour à la ligne automatiques). L'attribut align contenu dans la balise ouvrante permet de spécifier l'alignement du texte contenu dans le paragraphe.
  • <table></table>: balise permettant de créer un tableau. On note qu'il existe de nombreux attributs pour préciser le format du tableau (ici, border pour la taille de la bordure du tableau; bordercolor pour sa couleur; width pour sa largeur).
  • <tr></tr> (table row): balise qui, placée entre les balises table, permet de créer une ligne de tableau.
  • <td></td> (table data): balise qui, placée entre les balises table et td, permet de créer une cellule, soit le contenu des données d'un tableau.

Remarque: la balise <meta> est une balise qu'il n'est généralement pas nécessaire de fermer (selon le doctype) et qui contient des métadonnées (données descriptives quant au contenu). Elle peut être précisée par des attributs tels que content (nature du contenu/de la page) ou notamment charset (character set), attribut qui, défini en "utf-8", nous a permis ici d'écrire avec des caractères qui ne sont pas compris dans la table ASCII: les caractères accentués du français. Autrement, il aurait fallu écrire:

L'arborescence de travail a été créée !

Nous avons créé notre répertoire de travail pour le projet du mot "rêve" sur le web.
Voici le script bash qui nous a permis d’exécuter, par le biais de notre fenêtre de programmation, la création du répertoire PROJET-MOTS-SUR-LE-WEB.


Voici l'exécution du script sur le terminal bash et la vérification du bon déroulement de l'opération, en entrant dans les répertoires et en détaillant, grâce à la commande "ls", le contenu de chaque répertoire.


Enfin, vérifions ce que ça donne sur l'interface mac OS, dans le finder: