A Wikipédiából, a szabad lexikonból.
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Ez a bot a magyar wikipédia életrajzi lapjainak születési és halálozási
dátumait jegyzi be a megfelelő év- és nap-lapokra.
A következő argumentumokat ismeri:
-cat:kategória az adott kategória szócikkeit járja be
-links:lapnév minden lapot bejár, ami a lapnév lapról hivatkozva van
-file:textfájl a textfájlban hivatkozott lapokat járja be
(csak a [[lapnév]] fomájú hivatkozásokat tekinti)
-ro csak olvasás mód teszteléshez, nem módosít a lapokon
-noworklog nem tölti fel a munkanaplót a munka végeztével
Minden más paraméter egy lap címeként értelmeződik; ilyenkor csak ezt az
egy életrajzi lapot dolgozza fel a bot.
"""
__version__='0.3'
import sys, re, time, codecs
import wikipedia, date, pagegenerators, catlib
import szulhalGUI
monthIdx = date.formats['MonthName'][wikipedia.getSite().language()]
yearre = re.compile("([0-9]{3,4})")
monthre = re.compile("(?:" + '|'.join(date.makeMonthNamedList(wikipedia.getSite().language(), '%s')) + ")")
dayre = re.compile("(" + monthre.pattern + ") +([0-9]{1,2})")
datere = re.compile(yearre.pattern + "(?:\]\])?\.? +(?:\[\[)?(" + monthre.pattern + " [0-9]{1,2})")
headre = re.compile(u"^.*?\((.*)\) *[.:;,-]? *(.*?)(?:\.(?! *század)|;|$)")
log = codecs.open("szulhal.log", "w+", "utf-8")
class SzulHalBot:
def __init__(self, generator, headerLines = 10, readOnly = False, noLog = False):
self.generator = generator
self.headerLines = headerLines
self.readOnly = readOnly
self.noLog = noLog
self.modifications = False
def run(self):
data = []
log.write("= %s =\n" % time.asctime(time.gmtime(time.time())))
log.write(u"== Nem felismert életrajzi lapok ==\n")
for page in self.generator:
try:
text = page.get()
except wikipedia.NoPage:
wikipedia.output(u'HIBA: Nem találom a %s lapot' % page.title())
continue
except wikipedia.IsRedirectPage:
continue
for line in text.splitlines()[0:self.headerLines]:
hdmatch = headre.match(line)
if hdmatch:
dates = (datere.findall(hdmatch.group(1)) + [(None, None)])
else:
dates = []
if len(dates) >= 2:
person = (page.title(),) + dates[0] + dates[1] + (hdmatch.group(2),)
data.append((line, person))
break
else:
log.write("* [[%s]]\n" % page.title())
wikipedia.output(u"%s első %d sorában nem találtam a mintára illeszkedő fejet!" %
(page.title(), self.headerLines))
data = szulhalGUI.SzulHalGUI(data).display()
if not data:
return
for person in data[1]:
log.write("* [[%s]]\n" % person[0])
data = data[0]
log.write(u"== Sikeresen felismert életrajzi lapok ==\n")
for person in data:
self.checkPerson(*person)
if not self.noLog and self.modifications:
log.seek(0)
page = wikipedia.Page(wikipedia.getSite(), u"User:DhanakBot/Napló")
try:
naplo = page.get()
page.put("".join(log.readlines()) + naplo, u"Robot: Elvégzett munka naplózása")
except (wikipedia.NoPage, wikipedia.IsRedirectPage):
wikipedia.output("A naplót nem tudtam frissíteni")
def checkPerson(self, person, birthyear, birthday, deathyear, deathday, desc):
"""
Egy személy összes adatát frissítí a (legfeljebb) négy dátumlapon.
"""
log.write("* [[%s]]\n" % person)
pages = [
self.checkDatePage(birthyear, u"Robot: %s születése" % person, u"Születések",
person, dayCmp, birthday, u'†', deathyear, desc),
self.checkDatePage(birthday, u"Robot: %s születése" % person, u"Születések",
person, yearCmp, birthyear, u'†', deathyear, desc)
]
if deathyear and deathday:
pages += [
self.checkDatePage(deathyear, u"Robot: %s halála" % person, u"Halálozások",
person, dayCmp, deathday, u'*', birthyear, desc),
self.checkDatePage(deathday, u"Robot: %s halála" % person, u"Halálozások",
person, yearCmp, deathyear, u'*', birthyear, desc)
]
if not self.readOnly:
for (page, newText, comment) in filter(None, pages):
try:
page.put(newText, comment)
self.modifications = True
except wikipedia.EditConflict, arg:
log.write(u"** HIBA: %s\n" % arg.args[0])
wikipedia.output("HIBA: %s" % arg.args[0])
def checkDatePage(self, pageTitle, modCmt, *changeArgs):
"""
Egy személy adatait frissíti a pageTitle dátumlapon.
"""
log.write("** [[%s]] " % pageTitle)
try:
page = wikipedia.Page(wikipedia.getSite(), pageTitle)
text = page.get()
newText = self.changeSection(text, *changeArgs);
wikipedia.output("\n>>>>> %s <<<<<\n" % pageTitle)
wikipedia.showDiff(text, newText)
if (text != newText):
log.write(u"módosítva\n")
return (page, newText, modCmt)
else:
log.write(u"módosítása nem szükséges\n")
except SzulHalExn, arg:
wikipedia.output(arg.args[0])
log.write(arg.args[0] + "\n")
except wikipedia.NoPage:
log.write(u"nem létezik\n")
wikipedia.output(u'Nem találom a %s lapot' % page.title())
except wikipedia.IsRedirectPage:
log.write(u"redirekt\n")
pass
def changeSection(self, text, section, *changeArgs):
sectionre = re.compile("(== *" + section +
" *==\n)(.*?)(?===|{{|\[\[en:|\[\[Kat)", re.DOTALL)
(newText,subCnt) = sectionre.subn(InsertBirthDeath(*changeArgs), text, 1)
if subCnt == 0:
raise SzulHalExn(u"HIBA: nem találom a %s szakaszt" % section)
return newText
class SzulHalExn(Exception):
"""Hiba"""
class InvalidLine(Exception):
"""Ismeretlen szerkezetű sor"""
class InsertBirthDeath:
def __init__(self, personPage, whenCmp, when, otherChar, otherYear, description):
self.personPage = personPage
self.person = personPage.split(" (")[0]
self.whenCmp = whenCmp
self.when = when
self.otherChar = otherChar
self.otherYear = otherYear
self.description = description
def __call__(self, sectionMatch):
sectionLines = sectionMatch.group(2).splitlines()
if self.otherYear:
otherText = " (" + self.otherChar + " [[" + self.otherYear + "]])"
else:
otherText = ""
try:
for i in range(len(sectionLines)):
sectionLines[i] = self.tidy(sectionLines[i])
for i in range(len(sectionLines)):
if re.search(self.person, sectionLines[i]):
if otherText and not re.search(self.otherYear, sectionLines[i]):
sectionLines[i] += otherText
break
else:
line = "* [[" + self.when + "]]"
if not yearre.match(self.when):
line += "."
line += u" – [[" + self.personPage;
if self.person != self.personPage:
line += "|" + self.person;
line += "]]"
if self.description:
line += " " + self.description
line += otherText
sectionLines.append(line)
sectionLines.sort(self.whenCmp)
return sectionMatch.group(1) + '\n'.join(sectionLines) + "\n"
except InvalidLine, arg:
raise SzulHalExn(u"HIBA: ismeretlen szerkezetű sor: '%s'" % arg.args[0])
def tidy(self, line):
line = line.strip()
if line == "":
return line
match = tidyre.match(line)
if not match:
wikipedia.output(u"FIGYELEM: Ennek a sornak nem ismertem fel a szerkezetét: '%s'" % line)
return line
line = "* [[" + match.group(1) + "]]"
if not yearre.search(match.group(1)):
line += "."
line += u" – " + match.group(5) # groups 2, 3 and 4 are in yearre and dayre
if match.group(6) and match.group(7): # otherchar and otheryear
line += " ("
if match.group(6) == '*' or match.group(6).startswith("sz"):
line += "*"
else:
line += u"†"
line += " [[" + match.group(7) + "]])"
return line
tidyre = re.compile("^\* *(?:\[\[)?" +
"(" + yearre.pattern + "|" + dayre.pattern + ")" +
u"(?:\]\])?(?: *\.)? *[-–] *(.*?) *[.;]? *" +
u"(?: *\( *([*†+]|sz\S*?|m\S*?|†)(?: *| )(?:\[\[)?" +
yearre.pattern + "(?:\]\])? *\) *[.;]? *)?$")
class DateCmp:
def __init__(self, pattern, convert):
self.regex = re.compile(pattern)
self.convert = convert
def __call__(self, str1, str2):
if str1 == "" or str2 == "":
return cmp(str1 == "", str2 == "") # True is larger than False
(match1, match2) = map(self.regex.search, (str1, str2))
if not match1:
raise InvalidLine(str1)
if not match2:
raise InvalidLine(str2)
return cmp(self.convert(*match1.groups()), self.convert(*match2.groups()))
def dayCnvt(monthstr, daystr):
return (monthIdx(monthstr), int(daystr))
yearCmp = DateCmp(yearre, int)
dayCmp = DateCmp(dayre, dayCnvt)
def main():
# page generator
gen = None
readOnly = False
noLog = False
pageTitle = []
for arg in sys.argv[1:]:
arg = wikipedia.argHandler(arg, 'szulhal')
if arg:
if arg.startswith('-file:'):
gen = pagegenerators.TextfilePageGenerator(arg[6:])
elif arg.startswith('-cat:'):
cat = catlib.Category(wikipedia.getSite(), u"Kategória:" + arg[5:])
gen = pagegenerators.CategorizedPageGenerator(cat)
elif arg.startswith('-links:'):
page = wikipedia.Page(wikipedia.getSite(), arg[7:])
gen = pagegenerators.LinkedPageGenerator(page)
elif arg == '-ro':
readOnly = True
elif arg == '-noworklog':
noLog = True
else:
pageTitle.append(arg)
if pageTitle:
page = wikipedia.Page(wikipedia.getSite(), ' '.join(pageTitle))
gen = iter([page])
if not gen:
wikipedia.showHelp('szulhal')
else:
preloadinggen = pagegenerators.PreloadingGenerator(gen, pageNumber = 20)
bot = SzulHalBot(preloadinggen, readOnly = readOnly, noLog = noLog)
bot.run()
if __name__ == "__main__":
try:
main()
finally:
wikipedia.stopme()