Code GraderBot
Aller à la navigation
Aller à la recherche
import re
import sys
import urllib
import requests
import json
import hashlib
from bs4 import BeautifulSoup
baseurl = 'http://wikipast.epfl.ch/wikipast/'
content = '==GraderBot Report==\n'
def tokenizepage(pagetext) :
tokens = []
tk = pagetext.split('\n')
ignore = False
for t in tk:
if t:
if "==" in t:
if "Biographie" in t:
ignore = False
else:
ignore = True
if (t[0] == '*') and not ignore:
tokens.append(t)
return tokens
def checkpage(pagetext):
text = fetchPageData(pagetext)
tokens = tokenizepage(text)
grade = 6.0
grade -= checkentries(tokens)
if len(tokens) <= 10:
return 0.0
if checksource(tokens) > 0:
grade -= 0.5
if not checklinkpages(tokens, pagetext) :
grade -= 0.5
grade -= checkformat(tokens)
if not checkhyperwords(tokens) :
grade -= 0.5
return max(grade, 0)
def checksource(tokens):
r = '\*.*\[https?:\/\/w?w?w?\.?letemps[^\]]*\].*'
p = re.compile(r)
badsourced = 0
index = 0
global content
for t in tokens:
match = p.match(t)
if not match:
badsourced += 1
content += ("\n*Bad source at entry #" + str(index) + " : " + t + "\n")
index +=1
return badsourced
def checkentries(tokens):
malus = 0
malus += max(15 - len(tokens), 0)
global content
if (len(tokens) < 15):
content += ("\n*Only " + str(len(tokens)) + " entries when at least 15 are expected\n")
dates_isolator_expr = ['\* \[\[(.*)\]\] \/', '\*\[\[(.*)\]\]\:', '\*\[\[(.*)\]\]\/', '\*\[\[(.*)\]\] \/', '\*\s*\[\[([0-9]{4}).*']
hyperword_count = 0
chrono_count = 0
for t in tokens:
didmatch = False
hyperword_count += t.count("[[")
for i in dates_isolator_expr:
d = re.compile(i)
match = d.match(t)
if match:
didmatch = True
if not didmatch:
chrono_count += 1
malus += max(4 - hyperword_count, 0) * 0.5
malus += round(chrono_count/2)/4.0
if hyperword_count <= 4:
content += ("\n*Insufficient use of hyperwords\n")
if chrono_count > 0:
content += ("\n*" + str(chrono_count) + " entries did not have a chronology\n")
return min(malus, 4)
def checkformat(tokens) :
bullet_error = 0
date_error = 0
slash_or_dot_error = 0
malus = 0
global content
for t in tokens :
try:
formats = re.findall('(\*)\s*(\[\[\d{4}\.?\d{0,2}\.?\d{0,2}\]\])?\-?(\[\[\d{4}\.?\d{0,2}\.?\d{0,2}\]\])?[^\/]*(\/?)[^\.]*(\.?)\d*(.*)',t)
if formats[0][0] != '*' :
content += ("\n*No bullet point for line : " + t + "\n")
bullet_error += 1
if formats[0][1] == '' :
date = re.findall('\*\s*\[\[([0-9]*).*', t)
if not len(date) == 0:
content += ("\n*Error on date for line : " + t + "\n")
date_error += 1
if formats[0][3] == '' and formats[0][4] == '' :
content += ("\n*Invalid dot and slash arrangement for line : " + t + "\n")
slash_or_dot_error += 1
if bullet_error > 0:
malus += 0.25
if date_error > 0:
malus += 0.25
if slash_or_dot_error > 0:
malus += 0.25
except:
malus += 0.5
content += ("\n*Format completely invalid for line : " + t + "\n")
if malus > 0.5 :
return 0.5
else :
return malus
def checkhyperwords(tokens) :
hyperword_count_open = 0
hyperword_count_close = 0
global content
for t in tokens:
hyperword_count_open += t.count("[[")
hyperword_count_close += t.count("]]")
if hyperword_count_open != hyperword_count_close :
content += ('\n*Syntax of hyperwords is not respected\n ')
return False
if hyperword_count_close < 10 :
content += ('\n*Not enough hyperwords' + str(10) +'expected but' +str(hyperword_count_close) +'found \n' )
return False
return True
def checklinkpages(tokens, bio):
link_pages_count = 0
current_page = bio
global content
for t in tokens :
if isValidEntry(t) :
line_links = getHyperLinks(t, '')
for link in line_links :
if link != current_page : #isNewPage(link, ) && Il faut passer la liste de pages a vérifier, on ne l'a pas encore pour le test !
page = fetchPageData(link)
new_page_token = tokenizepage(page)
for new_tokens in new_page_token :
if areEntrySimilar(t, new_tokens) :
link_pages_count += 1
if link_pages_count < 5 :
content += ("\nOnly " + str(link_pages_count) + " linked pages are created / updated when at least 5 are expected\n")
return False
else :
return True
'''
Teste si la page donnée en argument existe déjà.
@oaram name : String
Le nom de la page à tester.
@oaram name : List(String)
La liste des pages existantes.
'''
def isNewPage(name, listOfPagesToCompare):
return (name in listOfPagesToCompare)
'''
À l'aide du titre de la page donné en argument,
récupère les données de cette page,
sous la forme d'une string
@param pageName : String
le titre de la page wikipast où aller chercher les données.
'''
def fetchPageData(pageName):
result=requests.post(baseurl+'api.php?action=query&titles='+pageName+'&export&exportnowrap')
soup=BeautifulSoup(result.text, "lxml")
pageData=''
for primitive in soup.findAll("text"):
if primitive.string != None:
pageData+=primitive.string
return pageData
'''
Vérifie que l'entrée donnée en argument soit bien une
entrée biographie (c'est à dire une entrée à puce commencant par une date)
@param entre : String
l'entrée à vérifier.
'''
def isValidEntry(entry):
if (entry[0:3] == '*[[' and entry[3:7].isdigit()) or (entry[0:4] == '* [[' and entry[4:8].isdigit()):
return True
else:
return False
'''
retourne une liste d'hyperLinks contenu
dans cette entrée sous une forme de liste
de String, mais en excluant de cette liste l'argument
toExclude.
'''
def getHyperLinks(entry, toExclude):
hyperLinks = re.findall('\[\[(.*?)\]\]', entry)
hyperLinks = set([x.split('|')[0] for x in hyperLinks])
if toExclude in hyperLinks: hyperLinks.remove(toExclude)
return list(hyperLinks)
'''
retourne une liste d'hyperLinks contenu
dans cette entrée sous une forme de liste
de String, mais en excluant de cette liste l'argument
toExclude.
'''
def getReferences(entry):
return re.findall('\[(.*?)\]', entry)
'''
Détermine si deux entrées sont identiques.
Pour ce faire on teste que
les dates, les lieux et la liste des hypermots
sont identiques.
(Pas de comparaison entre les PUBId!)
Si toutes les conditions énumérées ci dessus
sont satisfaites, alors on renvoit True,
autrement Talse.
@param entry1 : String
La première entrée à comparer
@param entry2 : String
La seconde entrée avec laquelle on compare la première
'''
def areEntrySimilar(entry1, entry2):
#la liste des hypermots inclus également la date
listOfHyperLinks1 = getHyperLinks(entry1, '')
listOfHyperLinks2 = getHyperLinks(entry2, '')
listOfReferences1 = getReferences(entry1)
listOfReferences2 = getReferences(entry2)
return (listOfHyperLinks1 == listOfHyperLinks2) and (listOfReferences1 == listOfReferences2)
def main(*args):
user='MasterBot'
passw='dhbot2019'
summary='GraderBot Notation'
# 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)
biopage = "Biographies"
biopage_txt = fetchPageData(biopage)
names = ""
if len(args) == 0:
names = re.findall("\|\s*?\[\[(.*?)\]\]" ,biopage_txt)
else:
names = args
for b in names:
content = ""
b = b.replace(' ', '_')
print(b + '\n')
grade = checkpage(b)
if grade > 5.95:
content += ("\nNo relevant error found.\n")
content += ("\n\nFINAL GRADE : " + str(grade) + " / 6.0\n")
payload = {'action': 'edit', 'assert': 'user', 'format': 'json', 'utf8': '', 'text': content,
'summary': summary, 'title': ('Discussion:' + b), 'token': edit_token}
r4 = requests.post(baseurl + 'api.php', data=payload, cookies=edit_cookie)