Pages : 1
#1 Le 28/04/2010, à 23:13
- sputnick
[JEU] #! /challenge/bash #8
<< challenge bash #8
Le challenge est ouvert à tous les langages de scripting ! scripteurs bash, python, perl, ruby… à vos claviers !
Robot web pour récupérer les nouveaux fils des sous-forums Ubuntu de son choix.
L'objectif est de réaliser un script qui va parser le forum afin d'y récupérer l'information requise ( 2 fils minimum ).
Les nouveaux fils devront apparaitre dans une boite de dialogue graphique passive et cliquable.
Pour les plus motivés, il y a un challenge bonus, c'est de récupérer les nouveaux messages d'un fil en particulier.
La propreté sera prise en compte, l'originalité pourquoi pas, la concision surement.
A vos éditeurs !
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#2 Le 28/04/2010, à 23:14
- sputnick
Re : [JEU] #! /challenge/bash #8
jde3 vainqueur pour la partie python et teg pour le bash
Dernière modification par sputnick (Le 18/06/2010, à 05:26)
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#3 Le 29/04/2010, à 10:49
- jde3
Re : [JEU] #! /challenge/bash #8
Bon, celui-là semble plus abordable que le précédent... Je me lance (en python), même si je ne suis pas sûr de faire l'interface graphique (qui ne me passionne pas...)
Dernière modification par jde3 (Le 29/04/2010, à 10:50)
Hors ligne
#4 Le 29/04/2010, à 13:19
- sputnick
Re : [JEU] #! /challenge/bash #8
Oui, ca peux très bien se faire en 10 lignes de code ^^
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#5 Le 29/04/2010, à 15:15
- jde3
Re : [JEU] #! /challenge/bash #8
Le mien ne sera pas en 10 lignes de code, mais ça peut motiver les suivants pour faire mieux : l'archive est à télécharger ici.
Pour exécuter ce code, il faut :
- avoir python d'installé (a priori toujours OK sur Ubuntu)
- taper
./parse_ubuntufr.py -h
dans un terminal pour avoir l'usage
PS : Merci à sputnick pour ton conseil.
PPS : je colle quand même le code pour les curieux...
#! /usr/bin/python
# -*- coding: utf-8 -*-
import getopt, sys
from parser import *
def usage ():
print "usage: " + sys.argv[0] + " [OPTIONS]"
print "OPTIONS:"
print "\t-h\t--help\t\tprint this help"
print "\t-f n\t--forum=n\tprint details for forum_id n (default will print list of forums)"
print "\t-m n\t--max-items=n\tonly print n most recent topics of a given forum (ignored if forum_id is not specified)"
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "hf:m:", ["help", "forum=", "max-items="])
except getopt.GetoptError, err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
forum_id = None
max_items = None
for o, a in opts:
if o in ("-h", "--help"):
usage()
sys.exit()
elif o in ("-f", "--forum"):
forum_id = int (a)
elif o in ("-m", "--max-items"):
max_items = int (a)
else:
assert False, "unhandled option"
if (forum_id == None):
print UbuntufrHomeParser ()
else:
print UbuntufrForumParser (forum_id, max_items)
if __name__ == "__main__":
main()
#! /usr/bin/python
# -*- coding: utf-8 -*-
import urllib, re, os
from item import *
class UbuntufrParser:
def __init__ (self, url, mask, item_class, max_items = None):
self.url = url
self.mask = mask
self.item_class = item_class
self.max_items = max_items
self.lines = urllib.urlopen (self.url).readlines ()
self.items = []
self.parse ()
def __str__ (self):
s = self.url + "\n"
if (len (self.items) == 0):
s = s + "\tRien de neuf par ici\n"
else:
for i in self.items:
s = s + "\t" + str (i) + "\n"
return s[:-1]
def parse (self):
in_an_important_div = False
for l in self.lines:
if (not (in_an_important_div) and (l.strip () == "<div class=\"tclcon\">")):
in_an_important_div = True
flines = []
elif (in_an_important_div):
if (l.strip () == "</div>"):
in_an_important_div = False
self.add_item (flines)
if (self.max_items != None and len (self.items) >= self.max_items):
break
else:
flines.append (l.strip ())
def add_item (self, flines):
l = flines.pop (0)
re_forum = re.match (self.mask, l)
if (re_forum):
(id, text) = re_forum.group (1, 2)
self.items.append (self.item_class (id, text))
class UbuntufrHomeParser (UbuntufrParser):
def __init__ (self):
UbuntufrParser.__init__ (self, "http://forum.ubuntu-fr.org/", "^<h3><a href=\"viewforum.php\?id=([0-9]+)\">(.*?)</a></h3>", Forum)
class UbuntufrForumParser (UbuntufrParser):
def __init__ (self, id, max_items = None):
UbuntufrParser.__init__ (self, "http://forum.ubuntu-fr.org/viewforum.php?id=" + str (id), "^<a href=\"viewtopic.php\?id=([0-9]+)\">(.*?)</a>", Topic, max_items)
#! /usr/bin/python
# -*- coding: utf-8 -*-
class Item:
def __init__ (self, id, title):
self.id = id
self.title = title
self.url = ""
def __str__ (self):
return "[" + str(self.url) + "] " + self.title
class Forum (Item):
def __init__ (self, id, title):
Item.__init__ (self, id, title)
self.url = "http://forum.ubuntu-fr.org/viewforum.php?id=" + str (self.id)
class Topic (Item):
def __init__ (self, id, title):
Item.__init__ (self, id, title)
self.url = "http://forum.ubuntu-fr.org/viewtopic.php?id=" + str (self.id)
if __name__ == "__main__":
print Item (10, "Installation d'Ubuntu")
Dernière modification par jde3 (Le 30/04/2010, à 15:48)
Hors ligne
#6 Le 29/04/2010, à 15:45
- sputnick
Re : [JEU] #! /challenge/bash #8
Même si ça te semble évident, si tu pouvais ajouter une brève explication de quoi faire avec tes 3 scripts, ça serais mieux pour les gens qui ne connaissent pas python.
Voir même en faire une archive à télécharger.
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#7 Le 30/04/2010, à 09:25
- nesthib
Re : [JEU] #! /challenge/bash #8
(abonnement)
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde auto – ♥ awk
⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn
Hors ligne
#8 Le 30/04/2010, à 14:46
- sputnick
Re : [JEU] #! /challenge/bash #8
@jde3, ton site d'upload, ça fait peur ! J'ai lâché l'affaire tellement les pubs sont invasives et les liens cachés.
Je te conseille http://dl.free.fr/
Dernière modification par sputnick (Le 30/04/2010, à 14:47)
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#9 Le 30/04/2010, à 15:49
- jde3
Re : [JEU] #! /challenge/bash #8
@jde3, ton site d'upload, ça fait peur ! J'ai lâché l'affaire tellement les pubs sont invasives et les liens cachés.
Je te conseille http://dl.free.fr/
C'est arrangé.
Hors ligne
#10 Le 04/05/2010, à 23:51
- sputnick
Re : [JEU] #! /challenge/bash #8
On dirait que personne n'est capable de faire ça en bash
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#11 Le 21/05/2010, à 18:14
- teg
Re : [JEU] #! /challenge/bash #8
Les nouveaux fils devront apparaitre dans une boite de dialogue graphique passive et cliquable.
On dirait que personne n'est capable de faire ça en bash
Forcément ça complique la tâche.. j'ai zappé l'interface.
#!/bin/bash
URL_INDEX="http://forum.ubuntu-fr.org/index.php"
URL_SSF="http://forum.ubuntu-fr.org/viewforum.php?id="
PROXY=""
FICHIER_TMP=/tmp/ubuntu-fr
if [ $PROXY ]
then
export http_proxy=$PROXY
fi
# Affichage du message d'usage du script et de la liste des forums disponibles :
liste_forums (){
echo ""
echo "Usage : $0 1 2 3"
echo " 1, 2 et 3 sont les numéros des forums à suivre"
echo ""
echo "Liste des forums consultables :"
# Téléchargement et affichage de la liste des forums :
rm -f $FICHIER_TMP
wget $URL_INDEX -O $FICHIER_TMP &> /dev/null
grep $(echo $URL_SSF | cut -d / -f 4) $FICHIER_TMP | cut -d "=" -f 3 | cut -d "<" -f 1 | sort -n | sed "s|\">|\t|"
rm -f $FICHIER_TMP
}
# Affichage des messages des sous-forums sélectionnés :
liste_messages (){
rm -f $FICHIER_TMP*
for i in $@
do
wget ${URL_SSF}${i} -O ${FICHIER_TMP}${i} &> /dev/null
done
grep viewtopic.php $FICHIER_TMP* | grep -v '#p' | cut -d ">" -f 2 | cut -d "<" -f 1 | grep -v Epingl > ${FICHIER_TMP}_msg
if [ $(which html2text) ]
then
while read ligne
do
echo $ligne | html2text
done < ${FICHIER_TMP}_msg
else
cat ${FICHIER_TMP}_msg
fi
rm -f $FICHIER_TMP*
}
if [[ $# = 0 ]]
then
liste_forums
else
liste_messages $@
fi
Pour l'usage et la liste des forums consultables :
./teg_ubuntu-fr_robot.bash
Pour l'utilisation :
./teg_ubuntu-fr_robot.bash 9 28 ...
Peut-être que j'essayerais d'améliorer ça encore. C'est sûr il n'y a rien d'exceptionnel mais j'avais besoin d'exercice !
A noter : possibilité de paramétrer un proxy dans le script et bonus pour ceux qui ont html2text d'installé.
Hors ligne
#12 Le 21/05/2010, à 19:31
- sputnick
Re : [JEU] #! /challenge/bash #8
Salut teg,
ce que je voit dans les choses qui me chiffonnent :
- tu pourrais traiter le flux à la volée sans utiliser de fichier temporaire
- les cuts à la chaine ça fait un peu peur
- for i in $@ peux s'écrire simplement for i, bash se débrouille tout seul.
- if [ $(which html2text) ] peux être simplifié et on peux utiliser un builtin bash : if type &>/dev/null html2text
- "USE MORE QUOTES!" Learn the difference between " and ' and `. See <http://wiki.bash-hackers.org/syntax/words> and <http://mywiki.wooledge.org/Quotes>.
Bien vu les deux modes de fonctionnement et bravo pour la présentation des ids avec le thème du sous forum.
Par contre, il semblerais plus logique de donner une url à la fin plutôt que le résumé.
Avec zenity ou notify-send on peux faire les deux en même temps.
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#13 Le 21/05/2010, à 19:37
- sputnick
Re : [JEU] #! /challenge/bash #8
@frafra, fini le avant de le montrer, nan ?
Merci d'indenter, ça donne pas envie de relire derrière, encore moins après ta présentation
@tous : pour récupérer les liens d'une page, je vous conseille fortement mech-dump qui est "livré" avec le module perl www-mechanize ( paquet libwww-mechanize-perl pour debian/ubuntu ). Cela s'utilise en l'appelant en ligne de commande. Voir :
mech-dump --help
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#14 Le 22/05/2010, à 05:59
- cacalex
Re : [JEU] #! /challenge/bash #8
Je suis peut-être vieux jeu, mais pourquoi ne pas passer par links/elinks au lieu de wget ?
ex: "links -dump"
Hors ligne
#15 Le 22/05/2010, à 09:54
- nesthib
Re : [JEU] #! /challenge/bash #8
ou par curl ?
perso j'utilise wget quand je dois récupérer les données dans un fichier et curl pour les avoir en sortie standard (même si tous deux savent faire ces deux opérations)
d'ailleurs si quelqu'un connait les différences principales entre wget et curl (faudrait que je fasse un post là dessus…)
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde auto – ♥ awk
⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn
Hors ligne
#16 Le 18/06/2010, à 04:57
- sputnick
Re : [JEU] #! /challenge/bash #8
Hé !
Je déclare jde3 vainqueur pour la partie python et teg pour le bash
Oui je sais ->[*]
Bon, j'ai pas eu le temps plus tot, mais j'ai une solution avec une partie bash assez courte pour récupérer les nouveaux items et une partie system+php+javascript pour l'interface de visualisation. C'est ce qui m'a semblé le plus adapté et le plus efficace.
Voici le code que je met sur un serveur en cron toutes les minutes :
forums-grabber.bash
#!/bin/bash
# affiche les nouveaux sujets surveilles ou les ouvrent dans firefox
. /etc/profile
# IDs à surveiller :
ids="35 78 23"
namesids[35]='Développement et programmation' namesids[78]='Console et terminal' namesids[23]='Trucs, astuces et scripts utiles'
for i in $ids; do
url="http://forum.kubuntu-fr.org/viewtopic.php?id=$(mech-dump 2>/dev/null --agent-alias='Linux Mozilla' --links --absolute "http://forum.kubuntu-fr.org/viewforum.php?id=$i" | \
pcregrep -o '^http://forum.kubuntu-fr.org/viewtopic.php\?id=\K\d+$' | sort -n | tail -1)"
if ! grep &>/dev/null "$url" ~/.ubuntuForumLog; then
d=$(date +"%A %d %B %H:%M")
{ echo "$(curl -s $url | awk -F '</?title>' '/<title>/{print $2}')%$url%${namesids[i]}%$d"
cat /home/www/sputnick-area.net/wordpress/forums.lst
} | sort -t% -k3 > /tmp/forums.lst__ && mv /tmp/forums.lst__ /home/www/sputnick-area.net/wordpress/forums.lst && echo "$url" >> ~/.ubuntuForumLog
fi
done
Il génère donc une sortie type csv dans forums.lst que mon code php va parser ensuite, voici mon interface :
http://www.sputnick-area.net/forums.php ( vous risquez de vous faire insulter )
et son code :
<?php session_start(); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="./styles.css" />
<link rel="icon" type="image/gif" href="./favicon-forums.ico" />
<script src="./JS/favicon.js" type="text/javascript"></script>
<script type="text/javascript">
setTimeout('location.reload(true)',1000*30); // refresh every 30 sec
function changeTitle(title) { document.title = title; }
</script>
<!--
written in 2010 by sputnick <gilles DOT quenot AT gmail DOT com>
-->
</head>
<body>
<?php
// on recupere la liste des sujets à consulter
// depuis un fichier systeme, avec sur chaque ligne
// cette syntaxe : "comment%url%sous-forum"
$filename = './forums.lst';
$fp = fopen( $filename, 'r' );
$file_contents = @fread( $fp, filesize( $filename ) );
fclose( $fp );
$lines = explode("\n", $file_contents);
$numlines = count($lines);
if ($numlines == 1) {
echo '<script type="text/javascript">
favicon.change("./favicon-white.ico");
</script>
<h2><div class="center">Pas de messages non lus</div></h2>' . "\n";
}
else {
echo '<script type="text/javascript">
favicon.change("./favicon-forums.ico");
</script>
<div class="center"><h2>Forum Ubuntu<i>: Les nouveaux fils...</i></h2></div>' . "\n";
}
// puis on traite chaque ligne pour l'afficher
for ($i = 0; $i < $numlines-1; $i++) {
$comment = explode("%", $lines[$i]);
$id = explode("=", $comment[1]);
$v = $i+1;
$new_entry[$i] = ' ' . $comment[3] . ' <a href="forums-del.php?entry=' . $v . '&id=' . $id[1] . '">' . $comment[0] . '</a>';
if ($_SESSION['sfr'] != $comment[2]) {
echo "<h3>$comment[2]</h3>";
}
$_SESSION['sfr'] = $comment[2];
echo '
<form action="forums-del.php?entry=' . $v . '" method="post">' . '
<input type="submit" value="Delete" /> ' . $new_entry[$i] . '
</form>';
}
?>
<br/><br/><br/><br/>
<div class="center">
<form action="forums-del.php?entry=all&id=true" method="post">
<input type="submit" value="BrowseAllLinks" />
<form action="forums-del.php?entry=all" method="post">
<input type="submit" value="DeleteAllStuff" />
</form>
</form>
</div>
<br/>
<br/>
<br/>
<div class="center">
<img alt="w3c xhtml valid" src="http://www.sputnick-area.net/bus-cars-camtars/web_badges/valid_xhtml_blue.png" />
<img alt="vim powered" src="http://www.sputnick-area.net/bus-cars-camtars/web_badges/vim_edited_blue.jpg" />
</div>
<?php
// alert via boite de dialogue JS si on a de nouveaux messages
if ($i != 0 && $i != $_SESSION['last']) {
echo '<script type="text/javascript">
alert("Check me bastard, right NOW !");
</script>';
$_SESSION['last'] = $i;
}
// changement du titre en fonction du nombre de messages à consulter
echo '<script type="text/javascript">
changeTitle("' . $i . ' items");
</script>';
echo "\n";
?>
</body>
</html>
Les features :
- boite de dialogue JS pour tous nouveau message ( on peut pas la rater )
- le favicon change de couleur si il y a des fils actifs
- le nombre d'items est indique dans l'onglet
- gere les sessions pour pouvoir échanger des variables entre les différents scripts php et savoir où on en est par session
quand on clique sur "delete", ca efface l'entrée via un sed dans le csv. Quand on clique sur un lien du forum, on passe sans le savoir ( ou faut etre rapide ) par http://www.sputnick-area.net/forums-del.php?entry=N&id=xxxx et ca efface ensuite aussi l'item.
"entry" étant le numéro de la ligne a effacer et "id", l'id du post sur le forum. Voici son code :
<?php session_start(); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="icon" type="image/gif" href="./facicon.ico">
<title>Forum Ubuntu delete item</title>
</head>
<body>
<?php
// si c'est pas moi, on ne modifie rien :
$ip = $_SERVER['REMOTE_ADDR'];
if ($ip != 'xx.xx.xxx.xx') {
echo '<script type="text/javascript">
alert("Usage reserve ' . $ip . ', hop charter direction /dev/null tudjuuu !");
window.location = "http://www.sputnick-area.net/forums.php"
</script>';
}
else {
$_SESSION['last']--;
if (isset($_GET['entry'])) {
if ($_GET['entry'] == "all") {
$cmd = ":> ./forums.lst";
system($cmd);
}
else {
// persistence des données simple et minimaliste ;)
// on va quand même pas sortir une BDD pour si peu ?! :D
$cmd = '/bin/sed -i "' . $_GET['entry'] . 'd" ./forums.lst';
system($cmd); // on te dit de le faire, tu le fais, point-barre !
// ( à la ligne )
if (isset($_GET['id'])) {
// on redirige vers le forum ad-hoc si on a cliqué sur ce lien
// dans la page précédente.
echo '<script type="text/javascript">
window.open("http://forum.kubuntu-fr.org/viewtopic.php?id=' . $_GET['id'] . '");
</script>';
}
}
}
// on redirige vers la page principale
echo "<meta http-equiv='refresh' content='0;http://www.sputnick-area.net/forums.php'>";
}
?>
</body>
</html>
Walla
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#17 Le 24/08/2010, à 18:38
- sputnick
Re : [JEU] #! /challenge/bash #8
Nouvelle version "tout en un" : http://www.sputnick-area.net/scripts/forums.php.html
Si ya des pros du php et que vous avez des commentaires sur mon code, je suis tout ouïe
Dernière modification par sputnick (Le 24/08/2010, à 18:39)
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
#18 Le 02/09/2010, à 21:43
- sputnick
Re : [JEU] #! /challenge/bash #8
Bon voici un lien pour ce projet qui a pris un peu d'ampleur ./viewtopic.php?pid=3703928#p3703928
Je sais, un peu partout, tout le monde s'entretue, c'est pas gai, mais d'autres s'entrevivent, j'irai les retrouver. Jacques Prévert
https://sputnick.fr
Hors ligne
Pages : 1