Discussion utilisateur:Orlodrim/Hawk-Eye-Bot

Dernier commentaire : il y a 10 ans par Orlodrim dans le sujet Quelques nouvelles

Projet modifier

Bonsoir !
Je reviens un peu à la charge, plusieurs « problèmes » me viennent à la tête. Mais chaque chose en son temps, je commence par ce qui est peut-être le principal : quand le programme se lance dans l'invite de commande, pas de soucis, les infos « défilent » les unes sous les autres. On est content, donc ; enfin JE suis content  . Cependant, le fait de mettre ces informations dans un fichier texte annexe (c'est en s'entraînant qu'on apprend, hein !), je me rend compte que l'on a seulement les données concernant le 10e mondial, c'est-à-dire les derniers. En fait, à chaque passage, les données sont écrasées, et on se retrouve seulement avec les dernières (cela n'était pas perceptible via la console). Tu vois le problème que je soulève ?
Si oui, y a-t-il une astuce bien connue des « adeptes » de Python pour remédier à ce problème, car de mon côté — et ce n'est pas faute d'avoir cherché — je ne vois pas bien comment capturer l'ensemble des données.
Hawk-Eye (d) 8 avril 2013 à 21:58 (CEST)Répondre

Bonsoir,
Ma boule de cristal me dit que tu écris dans le fichier comme ça :
for ligne in code_page.split('\n'):
  ...
    with open('machin.txt', 'w') as f:
      f.write('blabla')
(si c'est pas ça, donne-moi ton code source !)
Chaque appel à 'open' efface le fichier. La solution la plus simple est d'imbriquer la boucle 'for ...' dans le bloc 'with open...' plutôt que l'inverse :
with open('machin.txt', 'w') as f:
  for ligne in code_page.split('\n'):
    ...
      f.write('blabla')
Tu peux aussi stocker le code dans une liste, puis écrire le fichier d'un seul coup à la fin :
code_modele = []
for ligne in code_page.split('\n'):
  ...
    code_modele.append('blabla')
with open('machin.txt', 'w') as f:
  f.write('\n'.join(code_modele))
Si ton objectif ultime est d'écrire le résultat sur une page wiki et pas dans un fichier, tu as plutôt intérêt à utiliser la seconde solution.
Orlodrim [discuter] 9 avril 2013 à 23:59 (CEST)Répondre

Salut !

Trop forte ta boule de cristal, j'veux la même !  

Je m'en veux tellement de ne pas avoir pensé à la 1re des deux solutions tout seul, horrible ! Mais finalement, j'ai bien fait de te demander car j'ai opté pour le 2de, comme tu me le suggérais. Merci bien pour ce coup de pouce (=  ).

Comme tu peux le constater, je pense avoir fini mon programme (au passage, j'ai résolu plusieurs questions que je voulais te poser tout seul « comme un grand », hihi). Mais il me reste quelques autres questions, la plus prioritaire – car je me la pose depuis plusieurs jours déjà (pas plus d'une semaine quand même, je n'y connaissais rien !) – étant la première :

  1. Si on veut intervenir sur une liste de page (inclusions) contenant le modèle {{Exemple}} (je ne veux pas intervenir dessus, mais c'est juste pour … l'exemple !), comment doit-on travailler ? À partir d'une liste de fichier préalablement écrite sur un *.txt ? Y a-t-il une quelconque fonction de Pywikipedia permettant de l'obtenir directement ? Car moi, je travaille sur mon *.py et change à chaque fois manuellement le nom de la page dans mon fichier : page = wikipedia.Page(site, u'Article_1')page = wikipedia.Page(site, u'Article_2')
    • Qui découle de cette première question : ce serait bien du coup, que la console indique le nom de la page qu'elle traite (pas trop dur) et qu'elle demande si on travaille dessus, si on la passe (un peu à la manière de redirect.py). Mais pour ça, il faut d'abord que j'ai la réponse à la première question)
  2. Ma deuxième question concerne la régularité du programme (je viens d'être « accepté » sur Labs me semble-t-il). Lorsque l'on veut rendre un programme régulier dans le temps (une fois le lundi à h par exemple), comment ça se passe ? Est-ce à partir du module time, directement dans le code ? Ou bien est autre chose (un fichier annexe) ? J'ai besoin de bien des éclaircissements à ce propos, car je n'ai rien trouvé à droite à gauche.

Voilà, bien sûr, si tu as des exemples à me donner (sur des scripts qui sont en libre accès sur wiki/web) plutôt qu'une réponse qui te prends du temps, tu peux me donner les liens, j'en serai déjà ravis !

Dernière petite question subsidiaire : est-ce que l'emploi de « while i < X » avec incrémentation de 1 à i pour chaque tour de boucle augmente considérablement le temps d'exécution d'un script ? Car dans un autre programme que je viens de créer (qui ne contient aucune boucle « while ») et que je teste actuellement, le script est très rapide. Comparé à celui de mise à jour du modèle {{Top 10 ATP actuel}} qui utilise un while i < 2 (0 étant l'état « simple » et 1 l'état « double »), et depuis j'ai comme l'impression qu'il s'est largement ralenti !
Peut-être que tu voudrais voir le code d'ailleurs ?

Bonne soirée — Hawk-Eye (d) 11 avril 2013 à 00:21 (CEST)Répondre


Bonjour,

(question 1) La liste des inclusions s'obtient avec la fonction getReferences, par exemple :

site = pywikibot.getSite()
modele = pywikibot.Page(site, u'Modèle:Exemple')
for page in modele.getReferences(onlyTemplateInclusion=True):
  print page.title()

(question 2) Si tu veux lancer ton programme toutes les cinq heures, utilise cron. Ce n'est pas une fonction python, c'est un démon qui existe sur tous les systèmes de type Unix, et qui sert à lancer d'autres programmes à intervalle régulier. Il se configure avec la commande crontab. Par exemple, pour lancer un programme toutes les 2 heures (et à la minute 18), tu tapes "crontab -e" et tu ajoutes une ligne dans le fichier de la forme :

18 */2 *  *   *     /chemin/de/ton/programme.py

Faire tourner le programme python en permanence et mettre une fonction d'attente est possible, mais cela gaspille les ressources du serveur comparé à cron.

(question 3) Le temps d'exécution d'un while est la somme du temps d'évaluation de la condition (négligeable s'il s'agit d'une comparaison) plus le temps d'exécution de ce qu'il y a à l'intérieur, autant de fois que c'est répété. Écrire :

i = 0
while i < 3:
  print i
  i += 1

prendra exactement le même temps que :

i = 0
print i
i += 1
print i
i += 1
print i
i += 1

(note en passant, c'est équivalent à :

for i in xrange(3):
  print i

)

La lenteur peut venir du temps qu'il faut pour les les pages web. Sinon, je ne peux pas deviner.

Orlodrim [discuter] 12 avril 2013 à 19:14 (CEST)Répondre

Bonjour Orlodrim.
Question 1 :   ! Merci, il n'y avait pas cette explication sur Aide:Pywikipedia/manuelFR, du coup, j'étais coincé pour le « onlyTemplateInclusion=True ».
Question 2 : Hum, encore quelque chose de nouveau pour moi…   Si je comprend bien, c'est un fichier externe qui lance le programme.py à l'heure et selon la fréquence indiquée ? Cette technique est valable si on laisse l'ordi ouvert 24h/24, ou bien l'est-elle aussi quand on met le programme sur le serveur ?
Je ne comprend pas bien ce que veulent dire les astérisques dans la ligne de commande ?
(J'ai ouvert un compte sur Wikimedia Labs il y a peu, et je suis « accepté » dans le « Bots project ». Après, je ne m'en sors pas, je ne sais pas comment faire pour déposer les scripts. Comme je ne t'ai pas vu inscrit là-bas, je ne pense pas que tu puisse m'aider alors j'ai demandé un peu d'aide à ce propos à Quentinv57 (d · c).)
Bon dimanche — Hawk-Eye (d) 14 avril 2013 à 10:00 (CEST)Répondre
cron est un programme qui tourne en permanence en arrière-plan sur les systèmes Unix/Linux, pourvu que l'ordinateur soit en marche, et dont la seule fonction est de lancer les programmes listés dans ses fichiers de configuration (un par compte sur la machine). Le '*' veut dire "sans contrainte sur cette colonne" (explications : Crontab#Notation). Je ne sais pas s'il tourne sur ton ordinateur (ça dépend de ton système d'exploitation), mais il tourne certainement sur le serveur auquel tu as accès, qui fonctionne en permanence.
La procédure pour accéder aux serveurs semble être décrite sur Wikitech:Help:Access. Effectivement je n'ai pas de compte sur Wikimedia Labs, donc je ne pourrai pas te guider plus en détail.
Orlodrim [discuter] 14 avril 2013 à 10:29 (CEST)Répondre
Je suis sur Windows 8, donc je ne dois pas avoir accès à cron. Il va falloir que je me débrouille pour avoir accès aux serveurs de WikiLabs, alors. Je te tiens au courant ! — Hawk-Eye (d) 14 avril 2013 à 10:47 (CEST)Répondre

Quelques nouvelles modifier

Bonjour Orlodrim !

Quelques nouvelles à propos de la mise sur le serveur de certains scripts d'Hawk-Eye-Bot (d · c) : je n'ai finalement pas réussi, malgré de nombreux essais. Alors, je laisse un peu ça de côté pour le moment, ça m'a lassé   !

Sinon, le script où tu m'avais largement aidé fonctionne à merveille (voir {{Top 10 ATP actuel}}), et j'en ai fait un autre parallèlement qui fonctionne aussi bien pour mettre à jour les infobox des joueurs de tennis hebdomadairement.

Mais j'ai une petite question qui me trotte dans la tête :

Dans AWB, il y avait une possibilité de travailler uniquement dans un modèle précis. Par exemple, si j'ai besoin de travailler sur le paramètre légende d'un {{modèle-1}}, et que je ne veux pas modifier le {{modèle-2}} qui contient aussi un paramètre légende, alors je le précisais au sein du logiciel sus-cité. Avec Python, tu aurais un « tuyau » à me donner pour parvenir à la même chose assez simplement ? J'imagine bien que c'est possible mais je ne vois pas trop comment, en fait… Mais cela ne presse pas vraiment, c'est juste pour info, quand j'essaierai de résoudre des requêtes aux bots avec pywikipedia dans le futur, pour ne pas faire de bêtises en somme…  

Arf, et puis j'en ai une autre, en fait   ! Elle concerne ce que tu peux voir sur la page « Utilisateur:Hawk-Eye/Brouillon/4 ». Je cherche (désespérément) à remplacer les {{INC-d}} par le drapeau correspondant avec les données qui sont présentes au 1er tour. Par exemple, j'aimerai que David Ferrer se retrouve avec {{ESP-d}} à partir dès 1/8 de finale, et cela pour tous les joueurs à tous les tours. J'ai tenté de passer par les expressions régulières, pas de choix je pense, mais je m'embrouille et je pense que je cherche trop compliqué ! Tu pourrais me donner une piste, si tu vois comment régler cela ?

À bientôt & merci — Hawk-Eye (d) 7 mai 2013 à 20:00 (CEST)Répondre


Bonjour,

Pour remplacer dans un modèle, tu peux d'abord créer une regexp pour extraire le modèle qui t'intéresse et son contenu. Ensuite, tu appeles re.sub avec comme deuxième paramètre une fonction qui fait le remplacement à l'intérieur du modèle. Voilà une version minimale qui ignore les modèles contenant des modèles imbriqués (sinon créer la regexp devient assez compliqué, et les modèles imbriqués peuvent avoir des paramètres du même nom que le modèle principal). Dis-moi si tu as besoin d'aide pour gérer les cas plus complexes.

def remplace_simple(match):
  texte = match.group(0)
  # Cette fonction reçoit uniquement le texte à l'intérieur du modèle traité.
  # C'est ici qu'il faut implémenter le remplacement proprement dit.
  print u'Fonction remplace_simple appelée sur "%s"' % texte
  if '<nowiki>' in texte:
    # <nowiki> peut être problématique, cf. deuxième exemple (pour être fiable,
    # il faudrait aussi vérifier d'autres balises commes </nowiki>, <pre>,
    # <math>, <syntaxhighlight lang="text">, etc., et les commentaires).
    print u'Cas à traiter à la main...'
    return texte
  return texte.replace('|foo=', '|bar=')

def remplace_dans_modele(texte):
  # Trouve les occurrences d'un modèle donné et appelle remplace_simple pour chacune.
  # Exemple pour "Lien web"
  return re.sub(r'\{\{(\s|_)*[Ll]ien(\s|_)+web(\s|_)*\|[^{}]*\}\}', remplace_simple, texte)

print remplace_dans_modele(u'{{Lien web|foo=3}} {{Lien web truc|foo=4}} {{lien_web|foo=5}} abc')
print remplace_dans_modele(u'{{Lien web|bar=<nowiki>}}</nowiki>|foo=4}}')

Pour le (2) : tu peux faire une première boucle ligne par ligne pour lire les drapeaux connus dans un dictionnaire, puis une seconde pour remplacer ceux qui manquent.

def propagation_drapeaux(texte):
  drapeau_par_joueur = {}
  for ligne in texte.split('\n'):
    drapeau_par_joueur = {}
    #<si la ligne contient un drapeau et un joueur>
      if drapeau != 'INC-d':
	drapeau_par_joueur[joueur] = drapeau
  for ligne in texte.split('\n'):
    #<si la ligne contient un drapeau et un joueur>
      if drapeau == 'INC-d' and joueur in drapeau_par_joueur:
	#<remplacer le drapeau par drapeau_par_joueur[joueur] dans ligne>
    #<concaténer toutes les lignes>

Orlodrim [discuter] 8 mai 2013 à 01:02 (CEST)Répondre

Pour la première question, je n'ai pas encore eu l'occasion de pouvoir tester cela.
Par contre, pour la deuxième, c'est parfait  . J'ai un peu adapté à ma sauce, et ça marche parfaitement !
Je suis désormais face à un problème d'un autre type. J'ai un peu « bidouillé » avec les mises à jours de pywikipedia, et me voilà avec un message d'erreur dès lors que je lance un script que j'ai écrit (alors que ceux comme par exemple replace.py que je n'ai pas écrit fonctionnent très bien). Je te laisse admirer ça ! [1]. Ce qui pose problème est cela apparemment :
>>>from pywikibot.support import *
ImportError: No module named support
Je vois vraiment pas pourquoi ça se met à délirer… Bon, en attendant, je vais arrêter mes expériences. — Hawk-Eye (d) 14 mai 2013 à 12:11 (CEST)Répondre
J'avoue que je ne vois pas trop... essaye de mettre ton programme dans le même dossier que replace.py au lieu d'un sous-dossier "script", peut-être. Orlodrim [discuter] 15 mai 2013 à 23:01 (CEST)Répondre
Arfff  . Je vais retenter quelque chose demain alors ! Merci pour le conseil — Hawk-Eye (d) 15 mai 2013 à 23:16 (CEST)Répondre
Bon, ben … … … T'avais ENCORE raison ! Je ne vois pas trop pourquoi ça me donnait cette erreur du coup ! Mais en mettant mes scripts dans le répertoire de pywikipedia, impeccable  . Merci !!! —Hawk-Eye (d) 16 mai 2013 à 08:21 (CEST)Répondre
Pour info, je mettais mes scripts dans un dossiers scripts qui était placé à l'intérieur du répertoire pywikipedia. Voilà comment donc j'introduisais mes scripts, par exemple :
import re
import urllib
import sys
sys.path.append('C:/Users/''myname''/Documents/pywikipedia') # J'ajoute cela car par défaut il cherche dans le dossier local 'C:/Users/''myname''/Documents/pywikipedia/scripts'
import wikipedia
Tu vois ce qui pourrait clocher, toi, là-dedans ? Je ne vois pourtant pas d'horreur  … — Hawk-Eye (d) 16 mai 2013 à 08:41 (CEST)Répondre
Est-ce qu'il y a une copie de wikipedia.py dans le dossier scripts ? Si oui, supprime-la. Est-ce que ça marche en remplaçant "sys.path.append('C:/..." par "sys.path.insert(1, 'C:/..." ? Si oui, tu as probablement plusieurs copies de pywikipedia installées. Orlodrim [discuter] 16 mai 2013 à 21:12 (CEST)Répondre

Mais je vais encore avoir besoin de ton expérience. J'ai besoin de mettre à jour la version de pywikipedia avec ça. Je m'y prend comment, en gros ? (j'ai téléchargé TortoiseSVN pour Windows). Je préfère te demander, car en essayant tout seul, j'ai essuyé le problème ci-dessus, que tu m'as résolu.Hawk-Eye (d) 16 mai 2013 à 08:25 (CEST)Répondre

Je ne connais pas TortoiseSVN. Suivre les instructions de cette page de manuel devrait marcher. Orlodrim [discuter] 16 mai 2013 à 21:12 (CEST)Répondre
Retour à la page de l’utilisateur « Orlodrim/Hawk-Eye-Bot ».