« SourceBot » : différence entre les versions

De Wikipast
Aller à la navigation Aller à la recherche
(Annulation des modifications 37616 de Orthobot (discussion))
 
(18 versions intermédiaires par 4 utilisateurs non affichées)
Ligne 1 : Ligne 1 :




== Description ==
== Description ==


Le bot récupère toutes les données des Datafications Biographiques et détecte pour chaque datafication, l'absence éventuelle d'une source dans une ligne biographique et la signale.
Le bot récupère toutes les données des Datafications Biographiques ainsi que toutes les pages créer par des Bots et détecte pour chaque page, l'absence éventuelle d'une source dans une ligne biographique et la signale.
Il met à jour une page [[FactChecking]] qui liste les entrées non sourcées en associant une référence particulière à cet inconnue: cette référence est la date associée à l'entrée non sourcée.
Il met à jour une page [[FactChecking]] qui liste les entrées non sourcées en associant une référence particulière à cet inconnue: cette référence est la date associée à l'entrée non sourcée.
Il scanne régulièrement (toutes les heures) toutes les datafications biographiques et met à jour la page [[FactChecking]]. Pour chaque datification biographique, notre bot check si toutes les entrées de la biographie sont sourcées, si c'est le cas alors on passe à la suivante datafication, sinon le nom de la datafication ainsi que les différentes dates des entrées sourcées sont ajoutées au contenu de la page [[FactChecking]].
Il scanne régulièrement (toutes les heures) toutes les datafications biographiques ainsi que les autres pages de wikipast et met à jour la page [[FactChecking]].
Si une entrée non sourcée est mis à jour et devient sourcée, alors la date de cette entrée disparaitrera de la page [[FactChecking]].
 
Pour chaque datification biographique ainsi que pour toutes pages créées depuis le début du cours, notre bot check si toutes les entrées de ces pages sont sourcées, si c'est le cas alors on passe à la suivante datafication, sinon le nom de la datafication ainsi que les différentes dates des entrées non sourcées sont ajoutées au contenu de la page [[FactChecking]].
Si une entrée non sourcée est mis à jour et devient sourcée, alors la date de cette entrée disparaitra de la page [[FactChecking]].
Les entrées non sourcées comprennent aussi les entrées qui ont une source qui n'est pas letemps.ch.
Les entrées non sourcées comprennent aussi les entrées qui ont une source qui n'est pas letemps.ch.


Ligne 27 : Ligne 30 :


== Performances ==
== Performances ==
Notre bot repère toutes les entrées des pages des Datafications Biographiques qui ne sont pas ou mal sourcée:  
Notre bot repère toutes les entrées des pages des Datafications Biographiques qui ne sont pas ou mal sourcée:  
Ensuite celui-ci met à jour la page [[FactChecking]] en écrivant les dates où les sources sont manquantes. Nous avons commencé par afficher le numéro de la ligne où il n'y avait pas de source, puis nous nous sommes rendu comptes que quelques unes des entrées qui étaient sourcées l'étaient mal, nous avons donc décidé de rajouter à [[FactChecking]] toutes les entrées qui n'avaient pas une source provenant du site letemps.ch.  
Ensuite celui-ci met à jour la page [[FactChecking]] en écrivant les dates où les sources sont manquantes.  
 
Nous avons commencé par afficher le numéro de la ligne où il n'y avait pas de source, puis nous nous sommes rendu comptes que quelques unes des entrées qui étaient sourcées l'étaient mal, nous avons donc décidé de rajouter à [[FactChecking]] toutes les entrées qui n'avaient pas une source provenant du site letemps.ch.  
Une fois que nous avions récupérer tous les numéro des lignes mal sourcées/non sourcées, nous avons fait en sorte d'afficher la date associée à l'entrée non sourcée, car les indices ne permettaient pas de savoir directement quelles entrées étaient mal sourcées .  
Une fois que nous avions récupérer tous les numéro des lignes mal sourcées/non sourcées, nous avons fait en sorte d'afficher la date associée à l'entrée non sourcée, car les indices ne permettaient pas de savoir directement quelles entrées étaient mal sourcées .  


Ensuite nous avons repéré plusieurs types de formats de date existant.  
Ensuite nous avons repéré plusieurs types de formats de date existant.  
Notre bot permet de repérer les dates sous le format suivant :  *[[1999.02.01]]/ ou *[[1998.03.01]]: ou le format standard * [[1998.05.08]] /  
Notre bot permet de repérer les dates sous les formats suivant :
  *[[1999.02.01]]/ , *[[1998.03.01]]: , *[[1998.03.02]] / le format standard * [[1998.05.08]] /  


Si la date ne correspond a aucun de ces modèles alors l'affichage des sources mal sourcées sur  [[FactChecking]] sera moins performant: il n'affichera pas la date, mais la ligne où l'entrée est mal soourcée.
Si la date ne correspond a aucun de ces modèles alors l'affichage des sources mal sourcées sur  [[FactChecking]] sera moins performant: il n'affichera pas la date, mais la ligne où l'entrée est mal soourcée.
Pour réaliser tout cela nous avons utilisé des regular expressions afin de repérer la date et le lien dans chaque entrée. Cependant, si le format d'une entrée n'est pas respecté: si la date n'est pas le premier Hypermot alors il y aura des baisses de perfomances puisque l'affichage ne sera plus celui de la date:  
Pour réaliser tout cela nous avons utilisé des regular expressions afin de repérer la date et le lien dans chaque entrée. Cependant, si le format d'une entrée n'est pas respecté: si la date n'est pas le premier Hypermot alors il y aura des baisses de perfomances puisque l'affichage ne sera plus celui de la date:  
  ex: *[[Johny]]/[[Lausanne]] [[Election]] de [[Daniel Brélaz]] à l'[[Assemblée fédérale]]. pour Daniel Brélaz  
  ex: *[[Johny]]/[[Lausanne]] [[Election]] de [[Daniel Brélaz]] à l'[[Assemblée fédérale]].  
Ceci écrira : The wrong entries are the sources with the following dates: [ Johny ].  
  Ceci écrira pour Daniel Brélaz :
  The wrong entries are the sources with the following dates: [ Johny ].  
Cela peut-être assez problématique mais si le format officiel a été respecté alors cela ne posera pas problème.
Cela peut-être assez problématique mais si le format officiel a été respecté alors cela ne posera pas problème.
Finalement nous avons aussi ajouté toutes les pages qui ont été créées par des bots, afin que notre Bot ai accès à toutes les pages de wikipast.


== Code ==
== Code ==
Pour le coté serveur, devrait être lancé à peu près toutes les heures.
  <nowiki>
  <nowiki>
# coding: utf-8
import urllib
import urllib
import requests
import requests
Ligne 53 : Ligne 62 :
baseurl='http://wikipast.epfl.ch/wikipast/'
baseurl='http://wikipast.epfl.ch/wikipast/'
summary='Wikipastbot update'
summary='Wikipastbot update'
#names=['Daniel Brélaz']
 


# Login request
# Login request
Ligne 82 : Ligne 91 :
fullbios = code
fullbios = code


#get the list of all the names of the pages to check
 
protected_logins=["Frederickaplan","Maud","Vbuntinx","Testbot","SparqlBot","IB","SourceBot","PageUpdaterBot","Orthobot","BioPathBot","ChronoBOT","Amonbaro","AntoineL","AntoniasBanderos","Arnau","Arnaudpannatier","Aureliver","Brunowicht","Burgerpop","Cedricviaccoz","Christophe","Claudioloureiro","Ghislain","Gregoire3245","Hirtg","Houssm","Icebaker","JenniCin","JiggyQ","JulienB","Kl","Kperrard","Leandro Kieliger","Marcus","Martin","MatteoGiorla","Mireille","Mj2905","Musluoglucem","Nacho","Nameless","Nawel","O'showa","PA","Qantik","QuentinB","Raphael.barman","Roblan11","Romain Fournier","Sbaaa","Snus","Sonia","Tboyer","Thierry","Titi","Vlaedr","Wanda"]
depuis_date='2017-05-02T16:00:00Z'
 
#pages created by Bots or people in the class but not the ones like Fichier:Annonce biopath.png
liste_pages=[]
for user in protected_logins:
    result=requests.post(baseurl+'api.php?action=query&list=usercontribs&ucuser='+user+'&format=xml&ucend='+depuis_date)
    soup=BeautifulSoup(result.content,'lxml')
    for primitive in soup.usercontribs.findAll('item'):
        if primitive['title'][:7] != 'Fichier':
            liste_pages.append(primitive['title'])
       
#pages not to be considered.
bad_pages_list = ['Accueil', 'Bots','HypermotBot', 'OrthoBot', 'SourceBot','VandalBot','PageUpdaterBot', 'BioPathBot', 'SPARQLBot','InferenceBot/CheckerBot','LinkBot','CheckerBot', 'InferenceBot', 'MiningBot','Chronobot', 'ChronoBot', 'ImageBot','FormatBot', 'TangoBot']
liste_pages_correct = list(set(liste_pages) - set(bad_pages_list))
for p in liste_pages_correct:
    print(p)
       
 
allnames = []
allnames = []
for p in liste_pages_correct :
    allnames.append(p)
pattern = '\* ?\[\[([^\]]*)\]\].*'
pattern = '\* ?\[\[([^\]]*)\]\].*'
p = re.compile(pattern)
p = re.compile(pattern)
Ligne 95 : Ligne 125 :
             allnames.append(match.group(1))
             allnames.append(match.group(1))
              
              
#get code of each name page
 
fullCode = []
fullCode = []
for name in allnames:
for name in allnames:
     result=requests.post(baseurl+'api.php?action=query&titles='+name+'&export&exportnowrap')
     result=requests.post(baseurl+'api.php?action=query&titles='+name+'&export&exportnowrap')
     soup=BeautifulSoup(result.text, "lxml")
     soup=BeautifulSoup(result.text, "lxml")
    #soup=BeautifulSoup(result.text)
     code=''
     code=''
     for primitive in soup.findAll("text"):
     for primitive in soup.findAll("text"):
         code += primitive.string
         if primitive.string :
     fullCode.append((code, name))
            code += primitive.string
 
     if code :
        print(name)
        fullCode.append((code, name))




Ligne 112 : Ligne 143 :
# first element is a boolean: true if all entries are sourced
# first element is a boolean: true if all entries are sourced
#      false if sources are missing
#      false if sources are missing
# second element is a list of : all dates where the source is wrong.
# second element is a list of : (modification) all dates where the source is wrong.
#int: all the bad lines indexes
#int: all the bad lines indexes
def findBadPage(pageText):
def findBadPage(pageText):
Ligne 126 : Ligne 157 :
     r = '\*.*\[https?:\/\/w?w?w?\.?letemps[^\]]*\].*'
     r = '\*.*\[https?:\/\/w?w?w?\.?letemps[^\]]*\].*'
     p = re.compile(r)
     p = re.compile(r)
     dates_isolator_expr = ['\* \[\[(.*)\]\] \/', '\*\[\[(.*)\]\]\:', '\*\[\[(.*)\]\]\/']
     dates_isolator_expr = ['\* \[\[(.*)\]\] \/', '\*\[\[(.*)\]\]\:', '\*\[\[(.*)\]\]\/', '\*\[\[(.*)\]\] \/']
     index = 0
     index = 0
     allSourced = True
     allSourced = True
Ligne 134 : Ligne 165 :
         match = p.match(t)
         match = p.match(t)
         if not match:
         if not match:
            print(t)
             allSourced = False
             allSourced = False
             count = 0;
             count = 0;
             didmatch = False
             didmatch = False
            #Check if dates in any of the tree forms.
             for i in dates_isolator_expr :
             for i in dates_isolator_expr :
                 count +=1            
                 count +=1
             
                 d = re.compile(i)
                 d = re.compile(i)
                 match = d.match(t)
                 match = d.match(t)
Ligne 146 : Ligne 176 :
                     didmatch = True
                     didmatch = True
                     wrongDatesSources.append(match.group(1))
                     wrongDatesSources.append(match.group(1))
                   
             if not didmatch :
             if count == 3 and not didmatch :
                 wrongDatesSources.append('false source at line: ' + str(index))
                 wrongDatesSources.append('false source at line: ' + str(index))
                 otherSource = '\*.*\[(https?:\/\/.*)\].*'
                 otherSource = '\*.*\[(https?:\/\/.*)\].*'
Ligne 154 : Ligne 183 :
         index +=1
         index +=1
     return (allSourced, wrongDatesSources)
     return (allSourced, wrongDatesSources)


content = '\n'
content = '\n'
Ligne 171 : Ligne 201 :
         content += '\n\n'
         content += '\n\n'


#send to page FactChecking
 
'''content = '\n'
'''content = '\n'
content += 'Cette page liste toutes les biographies ayant des entrées non sourcées.'
content += 'Cette page liste toutes les biographies ayant des entrées non sourcées.'
Ligne 179 : Ligne 209 :
           'summary':summary,'title':'FactChecking','token':edit_token}
           'summary':summary,'title':'FactChecking','token':edit_token}
r4=requests.post(baseurl+'api.php',data=payload,cookies=edit_cookie)
r4=requests.post(baseurl+'api.php',data=payload,cookies=edit_cookie)
 
</nowiki>
</nowiki>

Dernière version du 30 mai 2017 à 11:35


Description

Le bot récupère toutes les données des Datafications Biographiques ainsi que toutes les pages créer par des Bots et détecte pour chaque page, l'absence éventuelle d'une source dans une ligne biographique et la signale. Il met à jour une page FactChecking qui liste les entrées non sourcées en associant une référence particulière à cet inconnue: cette référence est la date associée à l'entrée non sourcée. Il scanne régulièrement (toutes les heures) toutes les datafications biographiques ainsi que les autres pages de wikipast et met à jour la page FactChecking.

Pour chaque datification biographique ainsi que pour toutes pages créées depuis le début du cours, notre bot check si toutes les entrées de ces pages sont sourcées, si c'est le cas alors on passe à la suivante datafication, sinon le nom de la datafication ainsi que les différentes dates des entrées non sourcées sont ajoutées au contenu de la page FactChecking. Si une entrée non sourcée est mis à jour et devient sourcée, alors la date de cette entrée disparaitra de la page FactChecking. Les entrées non sourcées comprennent aussi les entrées qui ont une source qui n'est pas letemps.ch.

Exemples

Daniel Brélaz :

Notre bot recupère la page de Daniel Brélaz et elle retourne les dates de toute les entrées non-sourcées ou avec une autre source que letemps.ch . La première entrée possède un lien vers wikipedia qui n'est pas valide, et la deuxième n'a pas de source. Ce bot écrit sur FactChecking :

Daniel Brélaz

The wrong entries in this page are the sources with the following dates: [ 1975 , 1978 ]

Paul Maillefer :

Ici le lien est un lien wikipedia qui n'est pas une source valide. Dans le cas de cette entrée il écrit sur la page FactChecking :

Paul Maillefer

The wrong entries in this page are the sources with the following dates: [ 1911 ]

Performances

Notre bot repère toutes les entrées des pages des Datafications Biographiques qui ne sont pas ou mal sourcée: Ensuite celui-ci met à jour la page FactChecking en écrivant les dates où les sources sont manquantes.

Nous avons commencé par afficher le numéro de la ligne où il n'y avait pas de source, puis nous nous sommes rendu comptes que quelques unes des entrées qui étaient sourcées l'étaient mal, nous avons donc décidé de rajouter à FactChecking toutes les entrées qui n'avaient pas une source provenant du site letemps.ch. Une fois que nous avions récupérer tous les numéro des lignes mal sourcées/non sourcées, nous avons fait en sorte d'afficher la date associée à l'entrée non sourcée, car les indices ne permettaient pas de savoir directement quelles entrées étaient mal sourcées .

Ensuite nous avons repéré plusieurs types de formats de date existant. Notre bot permet de repérer les dates sous les formats suivant :

*1999.02.01/ , *1998.03.01: , *1998.03.02 / le format standard * 1998.05.08 / 

Si la date ne correspond a aucun de ces modèles alors l'affichage des sources mal sourcées sur FactChecking sera moins performant: il n'affichera pas la date, mais la ligne où l'entrée est mal soourcée. Pour réaliser tout cela nous avons utilisé des regular expressions afin de repérer la date et le lien dans chaque entrée. Cependant, si le format d'une entrée n'est pas respecté: si la date n'est pas le premier Hypermot alors il y aura des baisses de perfomances puisque l'affichage ne sera plus celui de la date:

ex: *Johny/Lausanne Election de Daniel Brélaz à l'Assemblée fédérale. 
 Ceci écrira pour Daniel Brélaz :
 The wrong entries are the sources with the following dates: [ Johny ]. 

Cela peut-être assez problématique mais si le format officiel a été respecté alors cela ne posera pas problème.

Finalement nous avons aussi ajouté toutes les pages qui ont été créées par des bots, afin que notre Bot ai accès à toutes les pages de wikipast.

Code

Pour le coté serveur, devrait être lancé à peu près toutes les heures.

import urllib
import requests
from bs4 import BeautifulSoup
import re

user='Vlaedr'
passw='Alextall007'
baseurl='http://wikipast.epfl.ch/wikipast/'
summary='Wikipastbot update'


# Login request
payload={'action':'query','format':'json','utf8':'','meta':'tokens','type':'login'}
r1=requests.post(baseurl + 'api.php', data=payload)

#login confirm
login_token=r1.json()['query']['tokens']['logintoken']
payload={'action':'login','format':'json','utf8':'','lgname':user,'lgpassword':passw,'lgtoken':login_token}
r2=requests.post(baseurl + 'api.php', data=payload, cookies=r1.cookies)

#get edit token2
params3='?format=json&action=query&meta=tokens&continue='
r3=requests.get(baseurl + 'api.php' + params3, cookies=r2.cookies)
edit_token=r3.json()['query']['tokens']['csrftoken']

edit_cookie=r2.cookies.copy()
edit_cookie.update(r3.cookies)


fullbios = ''
name = 'Biographies'
result=requests.post(baseurl+'api.php?action=query&titles='+name+'&export&exportnowrap')
soup=BeautifulSoup(result.text, "lxml")
code=''
for primitive in soup.findAll("text"):
    code+=primitive.string
fullbios = code


protected_logins=["Frederickaplan","Maud","Vbuntinx","Testbot","SparqlBot","IB","SourceBot","PageUpdaterBot","Orthobot","BioPathBot","ChronoBOT","Amonbaro","AntoineL","AntoniasBanderos","Arnau","Arnaudpannatier","Aureliver","Brunowicht","Burgerpop","Cedricviaccoz","Christophe","Claudioloureiro","Ghislain","Gregoire3245","Hirtg","Houssm","Icebaker","JenniCin","JiggyQ","JulienB","Kl","Kperrard","Leandro Kieliger","Marcus","Martin","MatteoGiorla","Mireille","Mj2905","Musluoglucem","Nacho","Nameless","Nawel","O'showa","PA","Qantik","QuentinB","Raphael.barman","Roblan11","Romain Fournier","Sbaaa","Snus","Sonia","Tboyer","Thierry","Titi","Vlaedr","Wanda"]
depuis_date='2017-05-02T16:00:00Z'

#pages created by Bots or people in the class but not the ones like Fichier:Annonce biopath.png
liste_pages=[]
for user in protected_logins:
    result=requests.post(baseurl+'api.php?action=query&list=usercontribs&ucuser='+user+'&format=xml&ucend='+depuis_date)
    soup=BeautifulSoup(result.content,'lxml')
    for primitive in soup.usercontribs.findAll('item'):
        if primitive['title'][:7] != 'Fichier':
            liste_pages.append(primitive['title'])
        
#pages not to be considered.
bad_pages_list = ['Accueil', 'Bots','HypermotBot', 'OrthoBot', 'SourceBot','VandalBot','PageUpdaterBot', 'BioPathBot', 'SPARQLBot','InferenceBot/CheckerBot','LinkBot','CheckerBot', 'InferenceBot', 'MiningBot','Chronobot', 'ChronoBot', 'ImageBot','FormatBot', 'TangoBot']
liste_pages_correct = list(set(liste_pages) - set(bad_pages_list))
for p in liste_pages_correct:
    print(p)
         

allnames = []
for p in liste_pages_correct :
    allnames.append(p)
pattern = '\* ?\[\[([^\]]*)\]\].*'
p = re.compile(pattern)
bioNames = fullbios.split('\n')
for c in bioNames:
  tk = c.split('\n')
  for t in tk:
    if t:
        match = p.match(t)
        if match:
            allnames.append(match.group(1))
            

fullCode = []
for name in allnames:
    result=requests.post(baseurl+'api.php?action=query&titles='+name+'&export&exportnowrap')
    soup=BeautifulSoup(result.text, "lxml")
    code=''
    for primitive in soup.findAll("text"):
        if primitive.string :
            code += primitive.string
    if code :
        print(name)
        fullCode.append((code, name))


# the argument is the plain text of the page
# this fonction returns a tuple:
# first element is a boolean: true if all entries are sourced
#       false if sources are missing
# second element is a list of : (modification) all dates where the source is wrong.
#int: all the bad lines indexes
def findBadPage(pageText):
    # get all the lines
    tokens = []
    tk = pageText.split('\n')
    for t in tk:
        if t:
            if t[0] == '*':
                tokens.append(t)
       
    #check if line is sourced
    r = '\*.*\[https?:\/\/w?w?w?\.?letemps[^\]]*\].*'
    p = re.compile(r)
    dates_isolator_expr = ['\* \[\[(.*)\]\] \/', '\*\[\[(.*)\]\]\:', '\*\[\[(.*)\]\]\/', '\*\[\[(.*)\]\] \/']
    index = 0
    allSourced = True
    wrongDatesSources = []
    
    for t in tokens:
        match = p.match(t)
        if not match:
            allSourced = False
            count = 0;
            didmatch = False
            for i in dates_isolator_expr :
                count +=1
               
                d = re.compile(i)
                match = d.match(t)
                if match:
                    didmatch = True
                    wrongDatesSources.append(match.group(1))
            if not didmatch :
                wrongDatesSources.append('false source at line: ' + str(index))
                otherSource = '\*.*\[(https?:\/\/.*)\].*'
                pOth = re.compile(otherSource)
                match = pOth.match(t)
        index +=1
    return (allSourced, wrongDatesSources)


content = '\n'
content += 'Cette page liste toutes les biographies ayant des entrées non sourcées.'
content +=  '\n==Bad page==\n'

badpage = []
wrongDatesSources = []
ok =True
for (c, name) in fullCode:
    (ok, wrongDatesSources) = findBadPage(c)
    if not ok:
        badpage.append(name)
        content += name
        content += '\n The wrong entries in this page are the sources with the following dates: ' 
        content += str(wrongDatesSources) 
        content += '\n\n'


'''content = '\n'
content += 'Cette page liste toutes les biographies ayant des entrées non sourcées.'
content +=  '\n==Bad page=='
content += '\n[[' + badpage[0] + ']]' '''
payload = {'action':'edit','assert':'user','format':'json','utf8':'','text':content,
           'summary':summary,'title':'FactChecking','token':edit_token}
r4=requests.post(baseurl+'api.php',data=payload,cookies=edit_cookie)