Un article de Wikipédia, l'encyclopédie libre.
# -*- coding: utf-8 -*-
# Image Terminator
# Code : fr:User:Dake - 2005
#Ameliorations des regex et debug : Darkonko (aout 2006), Baro (dec 2006), Phe (janiver 2007), Louperivois (mai 2007)
#refonte pour utiliser /w/api.php, fusion avec le script listant les images : fr:user:Darkoneko, avril 2008
# Basé sur le code "replace.py" de PyWikipedia
# Distributed under the terms of the PSF license.
import wikipedia, pagegenerators, catlib
import config, replace, re, sys, urllib, codecs
#========================================== PARAMETRES ========================
#Namespaces in which we can remove dead media links
allowedNamespaces = [
'0', # (main)
'10', #template
'12', #aide
'14', #category
'100', #portal
'102', #projet
'104' #reference
]
site = wikipedia.getSite()
#======================================== FIN PARAMETRES
def build_regex_from_title(title):
result = u''
for ch in title:
# |[] is invalid in title no need to quote it
if ch in u'()*.':
result += u'\\'
result += ch
result = result.replace(u' ', u'[ _]?')
result = u'[' + result[0].lower() + result[0].upper() + u']' + result[1:]
return result
class ReplaceRobotModified:
"""
A bot that can do text replacements.
"""
def __init__(self, generator, replacements, exceptions = [], acceptall = False, regex = False):
self.generator = generator
self.replacements = replacements
self.exceptions = exceptions
self.acceptall = acceptall
self.regex = regex
def checkExceptions(self, original_text):
"""
If one of the exceptions applies for the given text, returns the
substring which matches the exception. Otherwise it returns None.
"""
for exception in self.exceptions:
hit = exception.search(original_text)
if hit:
return hit.group(0)
return None
# réalise un seul remplacement, en utilisant seulement les paramètres
def doSingleReplacement(self, original_text, old, new, acceptall):
new_text = original_text
if self.regex:
# TODO: compiling the regex each time might be inefficient
oldR = re.compile(old, re.UNICODE)
new_text = oldR.sub(new, new_text)
else:
new_text = wikipedia.replaceExceptMathNowikiAndComments(new_text, old, new)
# wikipedia.output(u'\n>>> %s <<<' % page.title())
wikipedia.showDiff(original_text, new_text)
if original_text != new_text:
choice = ''
if not acceptall:
choice = wikipedia.inputChoice(u'Do you want to accept these changes?', ['Yes', 'No'], ['y', 'N'], 'N')
if acceptall or choice in ['y', 'Y']:
return new_text
return original_text
# réalise l'ensemble des remplacement
def doReplacements(self, original_text):
"""
Returns the text which is generated by applying all replacements to the
given text.
"""
new_text = original_text
for old, new, acceptall in self.replacements:
new_text = self.doSingleReplacement(new_text, old, new, acceptall)
return new_text
def run(self):
"""
Starts the robot.
"""
# Run the generator which will yield Pages which might need to be
# changed.
page = wikipedia.Page(site, self.generator)
original_text = ''
try:
# Load the page's text from the wiki
original_text = page.get()
if not page.canBeEdited():
wikipedia.output(u'Skipping locked page %s' % page.title())
return
except wikipedia.NoPage:
wikipedia.output(u'Page %s not found' % page.title())
return
except wikipedia.IsRedirectPage:
original_text = page.get(get_redirect=True)
match = self.checkExceptions(original_text)
# skip all pages that contain certain texts
if match:
wikipedia.output(u'Skipping %s because it contains %s' % (page.title(), match))
return
new_text = self.doReplacements(original_text)
if new_text == original_text:
wikipedia.output('No changes were necessary in %s' % page.title())
return
try:
page.put(new_text)
except wikipedia.EditConflict:
wikipedia.output(u'Skipping %s because of edit conflict' % (page.title()))
logUrl = "/w/api.php?format=xml&action=query&letype=delete&list=logevents&leprop=title&lelimit=5000"
txt = wikipedia.getSite().getUrl(logUrl)
findDeleted = re.compile(u'"6" title="[^"]+"')
deletedPics = findDeleted.findall(txt)
wikipedia.output(u"%s images trouvees sur 5000 suppression. " % ( len(deletedPics)) )
listInput = []
for pic in deletedPics:
pic = re.sub(u'"6" title="([^"]+)"','\g<1>', pic )
pic = urllib.unquote(pic)
listInput.append( pic ) #on rempli un tableau avec les noms d'image traités
#listInput = []
#listInput.append( "Image:Pistons.jpg" )
nbre = len(listInput)
for compteur in range(0, nbre) :
nom_image = listInput[compteur]
nom_image = urllib.unquote(nom_image.strip())
#phe janvier 2007
regexed_image = build_regex_from_title(nom_image[6:])
#Neko : Permet de detecter les cas du genre [[ Image : blabla.gif]] qui reviennent souvent
regexed_namespace = '[ _]*([Ii]mage|[Mm]edia)[ _]*:[ _]*'
#detection d'un lien du type [[ Image : blabla.gif | blablabla [[eventuel lien]] ]]
regexp = '\[\[%s%s.*?(\[\[.*?\]\].*?)*\]\]' % (regexed_namespace, regexed_image)
#ce regex repere les lignes du type "Image:blablabla|commentaire" que contiennent les <gallery>.
#un \n est ajouté lors du remplacement pour pallier au fait qu'il y en ai 2 detectés ici
regexpTagNoLinkGallery = '\n%s%s([ \t]*\|[^\n]*)?\n' % (regexed_namespace, regexed_image)
replaceTagNoLinkGallery = u'\n'
#ce regex detecte les <gallery> vides, le suivant les <center> vides (regulierement present autour des images, j'ai remarqué
regexpEmptyGallery = '<gallery>\s*</gallery>'
regexpEmptyCenter = '<center>\s*</center>'
#ce regex detecte si l'image a été passée en parametre à un modele
#possibilités : |Image:blabla.jpg ; |blabla.jpg ; |img=Image:blabla.jpg ; |img=blabla.jpg
regexpNoTag = u'(?P<beforeZone>\||=)[ \t]*(?:%s|)%s[ \t]*(?P<afterZone>(\}\}|\||\n|\rd))' % ( regexed_namespace, regexed_image)
replaceNoTag = r'\g<beforeZone>\g<afterZone>'
#on verifie si l'image sur laquelle on travaille n'existe bien ni ici ni sur commons. l'API permet de voir les deux d'un coup d'oeil
url = u"/w/api.php?format=xml&action=query&prop=imageinfo&titles=%s" % urllib.quote(nom_image.encode("utf-8"))
if not u'imagerepository=""' in wikipedia.getSite().getUrl(url): # "shared" si sur commons, "local" si en local, ?? si les deux, "" si n'existe sur ni l'un ni l'autre.
wikipedia.output(u"\03{lightblue}%s\03{default} existe." % nom_image)
continue
#utilisation de l'image :
url = u"/w/api.php?format=xml&action=query&list=imageusage&iutitle=%s" % urllib.quote(nom_image.encode("utf-8"))
txt = wikipedia.getSite().getUrl(url)
regexRelatedPages = re.compile(u'ns="(?P<ns>[0-9]+)" title="(?P<title>[^"]+)"')
relatedPages = regexRelatedPages.findall(txt)
#aucun lien trouvé
nb_pages = len(relatedPages)
if nb_pages == 0:
wikipedia.output(u"Aucun lien ne pointe sur \03{lightblue}%s\03{default}" % nom_image)
continue
wikipedia.output(u"Liens trouvés vers \03{lightyellow}%s\03{default}" % nom_image)
#suppression pour chaque page
for i in range(0, nb_pages) :
if not relatedPages[i][0] in allowedNamespaces :
wikipedia.output(u" \03{lightblue}%s\03{default} non traité" % relatedPages[i][1])
continue
wikipedia.setAction(u"Robot: retrait lien vers média effacé (%s); ménage dans les <tag> vides" % nom_image)
replaceList = [
(regexp, u'', True), #sans confirmation
(regexpTagNoLinkGallery, replaceTagNoLinkGallery, True), #sans confirmation
(regexpNoTag, replaceNoTag, True), #sans confirmation
(regexpEmptyGallery, u'', True), #sans confirmation
(regexpEmptyCenter, u'', True), #sans confirmation
]
bot = ReplaceRobotModified( relatedPages[i][1], replaceList, [], False, regex=True)
bot.run()