Овде ћу дати изворни код на брзину написаног бота за додавање категорије рођења. Бот је писан у Пајтону, користи pywikipedia framework и полуаутоматизован је (не ради измене над чланцима).

Идеја

уреди

На све чланке личности додати категорију рођења (нпр. Рођени 1235.). Ово бот самостално не може да уради (бар ја не умем:), па се бот користи само да даје предлоге, а човек мора да унесе категорију.

Начин рада

уреди

Бот се покрене, и на конзоли избацује потенцијалне чланке којима треба додати категорију рођења. На почетку изворног кода је гомила false-positive чланака, као и чланака људи којима се не зна датум рођења. Ако бот избаци false-positive чланак (тј. чланак који није везан за личност), треба га додати у прву листу (да не понавља), а ако избаци чланак од особе којој се не зна датум рођења (а вероватноћа да ће се сазнати је мала), треба га додати у другу листу (из истог разлога)

Закључак

уреди

Бот је нашао нешто око 300 чланака без категорије рођења. Одрадио је свој посао и иде у заслужену пензију. Можда ћу га покретати опет, али није нешто што треба стално да ради — довољно је да се покрене на месец-два дана (по мени). Поред тога да би био видљив свима и користио свима, стављам га овде пошто је врло вероватно да ћу изгубити изворни код ако остане само на мом рачунару:)

Изворни код

уреди

Није пријатан за око, али ради посао.

#!/usr/bin/python
# -*- coding: utf-8  -*-

"""
Glupi bot koji pokusava da nadje clanke na srpskoj vikipediji koji se odnose na ljude
i pokusava da detektuje one koji nemaju nalepljenu kategoriju "rodjeni NNNN."

To radi tako sto prodje za sve clanke (ulazni argument "-start !") i onda trazi da li se
pojavljuju reci "рођен", "rođen" i sl. i postom heuristikom pokusava da odstrani one clanke
koji se ne odnose na ljude. Sve sto nadje ispisuje u konzoli. Pogledajte i konstante na pocetku
za tweak-ovanje bota.
"""

import wikipedia as pywikibot
import pagegenerators

import re

# ovo su regularni izrazi koji nam pokazuju da u clanku postoji neka informacija da je neko rodjem
POSITIVE_MATCHES = [u".*\Wрођен.*", u".*\Wrođen.*", u".*\Wrodjen.*"]

# ovo su template-i koji sami ubacuju kategoriju "rodjeni ...", pa nas ti clanci ne zanimaju.
# U kôdu se dodaju "{{", tako da ovde treba bez njih navoditi template-e
TEMPLATES_PROVIDING_CATEGORY= [
            "Биографија", "биографија", "Biografija", "biografija",
            "Фудбалер", "фудбалер", "Fudbaler", "fudbaler",
            "Музичар", "музичар", "Muzičar", "muzičar",
            "Кутијица за глумце",
            "Почетник", "почетник", "Početnik", "početnik",
            ]

# lista regularnih izraza koji, ako se pojave, znace da ovaj clanak nije clanak o nekoj licnosti
NOT_PERSON_MATCHES = [
            u"\{\{година\}\}",
            u"\{\{хронологијадно\}\}",
            u"\{\{семитске државе и региони\}\}",
            u"\[\[категорија:\s*државе у\s*",
            u"\[\[категорија:\s*градови",
            u"\[\[категорија:\s*насељена места у\s*",
            u"\[\[категорија:\s*српске породице\]\]",
            u"\[\[категорија:\s*измишљени ликови\]\]",
            u"\[\[категорија:\s*филмски ликови\]\]",
            u"\[\[категорија:\s*стрип јунаци\]\]",
            u"\[\[kategorija:\s*izmišljeni likovi\]\]",
            ]

# ovo su false-positives clanci koje nisu mogli biti odstranjeni nikako drugacije,
# a koje filtriramo ovakvom enumeracijom. Ovo je trenutna lista (23.03.2010.), tako da
# ce u medjuvremenu verovatno da se nakupi jos ovakvih - potrebno ih je onda dodati u
# ovu listu (ili pokusati sa novima da se pronadje jos neka heuristika)
SKIP_ARTICLES = [
            "18. век",
            "30×11 календар",
            "Anti-Flag",
            "Bluz",
            "Braća Vačauski",
            "Buba bombarder",
            "Dan pronalazača",
            "E=mc²",
            "Ekran (Sombor)",
            "Erreway",
            "Ju grupa",
            "King of Pop",
            "Kiss",
            "Kruševac Open",
            "Lajka",
            "Legija časti",
            "Paulijanska tužba",
            "Ples duhova",
            "Pokret bezemljaša Brazila",
            "Projekat Ekselsior",
            "Rolabogan",
            "Tcl",
            "The Godfather The Game 2",
            "Tokio Hotel",
            "Univerzitet Stanford",
            "Vika",
            "Zmaj (Točak vremena)",
            "Živeti sa...",
            "Ђогани",
            "Јединствени матични број грађанина",
            "Јеховини сведоци",
            "Југовићево (Аеродром)",
            "Џој дивижон",
            "Алфавил",
            "Алфеј, Филаделф и Кирин",
            "Амбер",
            "Амфијан и Едесије",
            "Анархизам",
            "Анархо панк",
            "Антика на тлу Србије",
            "Апгар тест",
            "Атаксија-телеангиектатика",
            "Атлетика на Летњим олимпијским играма 2000. — бацање кладива за жене",
            "Аватар (филм)",
            "Банат",
            "Били смо војници",
            "Битка за Бању Ковиљачу",
            "Битка за Вуковар",
            "Битка за Нормандију",
            "Битка код Азенкура",
            "Битка код Кресија",
            "Бијело дугме",
            "Благоевградска област",
            "Блек (група)",
            "Бобисокс",
            "Богородичина црква у Паризу (роман)",
            "Буснови",
            "Бјути квинс",
            "Бундеслига",
            "Ватромет",
            "Везендонк песме",
            "Везир",
            "Виолина",
            "Високо",
            "Вијетнамски календар",
            "Вијетнамски рат",
            "Војвођански Мађари",
            "Гимназија Бања Лука",
            "Горштак (филм)",
            "Гозу (филм)",
            "Град уметности и науке",
            "Градска општина Звездара",
            "Давитељ против давитеља",
            "Датуми у Ратовима звезда",
            "Дворац Фонтенбло",
            "Дејановићи",
            "Делије север",
            "Делфи",
            "Демографија Маурицијуса",
            "Демографија Мађарске",
            "Демографија Сао Томе и Принципеа",
            "Деца Јозефа Гебелса",
            "Децембар",
            "Дисова награда",
            "Долина Аосте",
            "Домреми ла Писел",
            "Дрвар у Народноослободилачкој борби",
            "Држављанство",
            "Европесма-Еуропјесма",
            "Европско првенство у фудбалу за играче до 21 године 2009.",
            "Ефес",
            "Елбрус",
            "Епископ",
            "Естонија на Летњим олимпијским играма 2008.",
            "Заливски рат",
            "Звезда је рођена (филм из 1937)",
            "Звер из Жеводана",
            "Зелени трезор",
            "Златни глобус за најбољег главног глумца у играном филму (драма)",
            "Златни глобус за најбољег глумца у играном филму (мјузикл или комедија)",
            "Златни глобус за најбољу главну глумицу у играном филму (мјузикл или комедија)",
            "Знамените личности града Ниша",
            "Зороастрички календар",
            "Изборна скупштина САНУ 2009.",
            "Између два зла",
            "Индоевропљани",
            "Интернет",
            "Ирски шпанијел за воду",
            "Ислам Грчки",
            "Исламски календар",
            "Историја Србије у средњем веку",
            "Историја Шпаније",
            "Историја Свазиленда",
            "Историја Срба пре Немањића",
            "Историја кинематографије у Румунији",
            "Исусов живот према Новом завету",
            "Исусово рођење у ликовној умјетности",
            "Италијани",
            "КГБ",
            "Канони светих отаца",
            "Карикатура",
            "Катињски масакр",
            "Квалификације за Светско првенство у фудбалу 2010. — УЕФА",
            "Квалификације за Светско првенство у фудбалу 2010. — УЕФА — група 7",
            "Квант",
            "Кешко",
            "Кинески радио интернационал",
            "Класична гитара",
            "Клуб студената технике",
            "Козма и Дамјан",
            "Кокејнов синдром",
            "Колубарска битка",
            "Константинова династија",
            "Крав мага",
            "Краљевски апартман",
            "Култура Сједињених Америчких Држава",
            "Кумодраж (село)",
            "Кућа легата",
            "Латинска Америка",
            "Лечеро",
            "Лигурија",
            "Лиса Хејз",
            "Лорди",
            "Мадонина дискографија",
            "Манастир свете Тројице у Кикинди",
            "Мара (регион)",
            "Маргаретен",
            "Маршал Совјетског Савеза",
            "Маршалска Острва",
            "Махабхарата",
            "Мађари у Народноослободилачкој борби",
            "Мађарска на Летњим олимпијским играма 1968.",
            "Мађарска на Летњим олимпијским играма 1972.",
            "Мбабане",
            "Мегатренд универзитет",
            "Мемнон"
            "Менетије",
            "Мерцедес гран при",
            "Међународно друштво за свесност Кришне",
            "Милица",
            "Мингуо календар",
            "Митрополија дабробосанска",
            "Морганатски брак",
            "Награда Борислав Михајловић Михиз",
            "Награда Душан Васиљев",
            "Награде на светским првенствима у фудбалу",
            "Наис и Медијана",
            "Народна банка Србије",
            "Немачка Аустрија",
            "Немачка лака крстарица Келн",
            "Немири на Косову и Метохији 2004.",
            "Неродимље",
            "Норвешка партија напретка",
            "Одбрана Сплита септембра 1943",
            "Окружни комитет СКОЈ-а за Дрвар",
            "Оловни војник",
            "Орден народног хероја",
            "Орентије, Фарнакије, Ерос, Фирмос, Фирмин, Кириак и Лонгин",
            "Орловић",
            "Остроготи",
            "Оцикет",
            "Пакистан",
            "Пањковић",
            "Педагошки факултет Универзитета у Новом Саду",
            "Печат кнеза Стројимира",
            "Питагорина теорема",
            "Плазма торта",
            "Планина Броукбек",
            "Плезентвил (филм)",
            "Подела Индије",
            "Позориште у кући",
            "Поп Ћира и поп Спира",
            "Последњи процват старе српске књижевности",
            "Похвала лудости",
            "Правитељствујушчи сенат црногорски и брдски",
            "Православни богословски факултет Универзитета у Београду",
            "Празници у СФРЈ",
            "Први београдски специјални борбени одред Српски Гестапо",
            "Први светски рат",
            "Предромантизам у српској књижевности",
            "Преторијанска гарда",
            "Принц Чарлс (острво)",
            "Пријатељи (роман)",
            "Пророчанство папа",
            "Пројекције становништва",
            "Птолемејиди",
            "Растафаријанство",
            "Ратови ружа",
            "Реализам у српској књижевности",
            "Рибникари",
            "Римска књижевност",
            "Ромска химна",
            "Ромулијана",
            "Ропство",
            "Руске авангарде",
            "Савез пионира Југославије",
            "Савезна Република Југославија",
            "Свердловска област",
            "Света тројица",
            "Светски рекорди у атлетици на отвореном",
            "Светско првенство у атлетици 2007. мушки, маратон",
            "Северна Кореја",
            "Серија А (Бразилски фудбалски шампионат)",
            "Сестре Бозвел",
            "Сикрет гарден",
            "Сингидунум",
            "Сиродил",
            "Скот Бернард",
            "Случајни партнери (албум)",
            "Смак",
            "Солунска краљевина",
            "Социјалдемократска партија Немачке",
            "Средњовековна филозофија",
            "Српско-албанско пријатељство",
            "Српско војничко гробље на Зејтинлику",
            "Стандардни мандарински језик",
            "Становништво",
            "Становништво Аустралије",
            "Становништво и насеља на Антарктику",
            "Статуета Јоаким Вујић",
            "Стигма (рана)",
            "Суђаје",
            "Суперлига Србије у фудбалу 2008/09.",
            "Сфинкс",
            "Сједињене Америчке Државе",
            "Табан",
            "Тасавуф",
            "Телевизија",
            "Тесла (презиме)",
            "Травник",
            "Трајанов мост",
            "Требиње",
            "Трискаидекафобија",
            "Тровање кисеоником",
            "Трофин и Тал",
            "Убијци",
            "Удружење студената електротехнике Европе — Локални комитет Београд",
            "Улица Бауман (Казањ)",
            "Универзитет у Београду",
            "Упитнички системи",
            "Ухвати ме ако можеш",
            "Филип Вишњић и устаничка епика",
            "Финарфин",
            "Фирентински календар",
            "Фотографија",
            "Хиспанија",
            "Хитлер, последњи дани",
            "Хитлерјугенд",
            "Холандска партија слободе",
            "Хрватска дијаспора",
            "Хронична мијелоилна леукемија",
            "Хуњади",
            "Црвени крст",
            "Црква успења пресвете Богородице у Вођеници",
            "Црни пантери",
            "Чикано",
            "Чиле",
            "Човек са гвозденом маском",
            "Човек слон (филм)",
            "Човечја рибица",
            "Штафета младости",
            ]

# ljudi kojima nije poznata godina rodjenja (tj. pise npr. "oko 345. godine),
# ali dok se ne smisli heuristika za ovo, ovako ce se trebe:)
UNKNOWN_BIRTH_YEAR = [
            "Faust",
            "Lukul",
            "Marko Fabije Kvintilijan",
            "Spartak",
            "Jovan Simić Bobovac",
            "Јевстатије I",
            "Јанко Катић",
            "Јован Владимир",
            "Јован Дамаскин",
            "Јован Дошеновић",
            "Јован Касијан",
            "Јован Крститељ",
            "Јован Кушчник",
            "Јован Малала",
            "Јовијан",
            "Јосиф Песмописац",
            "Јошуа",
            "Јурај Далматинац",
            "Јуста Грата Хонорија",
            "Љубљен",
            "Џанг Сји",
            "Џон Кабот",
            "Ал Кинди",
            "Алекса Дундић",
            "Александар Солунски",
            "Алексије Андрејевић",
            "Алимпије Столпник",
            "Алкуин",
            "Алтоман Војиновић",
            "Ана Болен",
            "Антиох III Велики",
            "Антонина Никејска",
            "Антонио Полајуоло",
            "Антонио Сера",
            "Антоније Велики",
            "Аристид (војсковођа)",
            "Аристовул Британски",
            "Аристофан",
            "Арминије",
            "Атанасија Егинска",
            "Аурелије Виктор",
            "Ауреол од Арагона",
            "Ахил Лариски",
            "Бонос",
            "Валентин",
            "Василије Велики",
            "Василије Трбић",
            "Венијамин",
            "Вукан (рашки велики жупан)",
            "Глицерије",
            "Горгија",
            "Гордијан I",
            "Гордијан II",
            "Гордије Цезарејски",
            "Григорије Горњачки",
            "Григорије Давидовић-Обшић",
            "Григорије Омиритски",
            "Деције Трајан",
            "Донатело",
            "Дунс Скот",
            "Евагрије Схоластик",
            "Ефор",
            "Епифаније Кипарски",
            "Епихарм",
            "Жак де Моле",
            "Завида",
            "Ибик",
            "Ивајло",
            "Игнасио де Лојола",
            "Илија Милосављевић Коларац",
            "Илија Муромец",
            "Ирина Асен",
            "Иринеј Лионски",
            "Исус",
            "Калојан",
            "Касиодор Сенатор",
            "Катарина Хауард",
            "Клеопатра I",
            "Клеопатра IV",
            "Клеопатра VII од Египта",
            "Клеопатра Еуридика",
            "Константин IV",
            "Константин Драгаш Дејановић",
            "Константин Михаиловић",
            "Константин Немањић",
            "Константин Хагаренски",
            "Констанс I",
            "Констанс II Погонат",
            "Корнелије Непот",
            "Коцељ (кнез)",
            "Лазар Марин",
            "Лијутпранд Кремонски",
            "Лисип",
            "Лука Столпник",
            "Магнус Максимус",
            "Макрин",
            "Максенције",
            "Максим Грк",
            "Марија (мајка Исусова)",
            "Маркион",
            "Маркијан",
            "Маркијан Цариградски",
            "Марко Антоније",
            "Марко Трачески",
            "Мернептах",
            "Мартина (Ираклијева супруга)",
            "Мартинијан Цезарејски",
            "Матасвента",
            "Методије Цариградски",
            "Михаило Војислављевић",
            "Михаило Псел",
            "Михајло Вишевић",
            "Мијамото Мусаши",
            "Мутимир",
            "Мухамед",
            "Мухамед Ал Хорезми",
            "Никола Мирликијски",
            "Никола Наљешковић",
            "Нифонт Атонски",
            "Нумеријан",
            "Отон Фрајзиншки",
            "Павле Брановић",
            "Павле Ирић",
            "Павле Поповић (совјетник)",
            "Павле Тивејски",
            "Папа Елеутерије",
            "Папа Урбан V",
            "Песценије Нигер",
            "Петар Ћуда-Мустафа Паша",
            "Петар Чудотворац",
            "Петроније Максим",
            "Питер Бројгел Старији",
            "Прибац Хребељановић",
            "Прокопије (противцар)",
            "Птолемеј IV Филопатор",
            "Публије Теренције Афер",
            "Радивој Остојић",
            "Радојко Којадиновић",
            "Рамзес II",
            "Ричард Руфус",
            "Рокселана",
            "Ромил Светогорски",
            "Ромул Августул",
            "Руфин Аквилејски",
            "Сампсон Странопримац",
            "Сапфа",
            "Сар (војсковођа)",
            "Свети Трифун",
            "Сидарта Гаутама",
            "Симеон Богопримац",
            "Симеон Нови Богослов",
            "Симеон Столпник Старији",
            "Симон Петар",
            "Созомен",
            "Софија (супруга Јустина II)",
            "Софокле",
            "Стефан Урош III Дечански",
            "Стефан Урош II Милутин",
            "Страбон",
            "Талес из Милета",
            "Теодосије Антиохијски",
            "Теофилакт Симоката",
            "Тиберије III Апсимар",
            "Тимотеј Ефешки",
            "Тома Аквински",
            "Тома Архиђакон",
            "Тома Магистар",
            "Тома Прељубовић",
            "Тома Словен",
            "Томаида Александријска",
            "Тотила",
            "Тристан да Куња",
            "Тукидид",
            "Филип Арабљанин",
            "Фирмикус",
            "Хереније Етрускус",
            "Цвеи Хао (песник)",
            "Часлав Клонимировић",
            
            ]

class GodineBot:

    def __init__(self, generator):
        self.generator = generator

    def run(self):
        for page in self.generator:
            # odbacujemo odmah one clanke koji su u listi clanaka za odbacivanje
            if page.title() in SKIP_ARTICLES:
                continue
            # odbacujemo i clanke za one ljude za koje se ne zna godina rodjenja
            if page.title() in UNKNOWN_BIRTH_YEAR:
                continue
            # odbacujemo viseznacne odsrednice
            if page.title().endswith("(вишезначна одредница)"):
                continue
            if page.title().startswith("Општина "):
                return
            if page.title().startswith("Оскар за најбољ"):
                return
            if page.title().startswith("Списак "):
                return
            if page.title().startswith("ФК "):
                return
            if page.title().startswith("Фудбалска репрезентација "):
                return
            if page.title().startswith("Хронологија "):
                return
            self.treat(page)

    def treat(self, page):
        try:
            text = page.get()
            # trazimo da li se pojavljuje tekst "rodjen"
            found = False
            for to_search in POSITIVE_MATCHES:
                found = found or (re.search(to_search, text, re.IGNORECASE | re.UNICODE) != None)
            if not found:
                return
            # proveri da nije neka od strana koje nas sigurno ne zanimaju
            if is_person_article(text) == False:
                return
            # proveri jel ima neki od sablona koji automatski dodaju kategoriju
            if is_template_providing_category(text):
                return
            # proveri jel vec ima kategoriju
            if already_has_category(text):
                return
            # proveravamo da li ima godine u delu teksta koji pominje rodjenje
            if not has_numbers(text):
                return
            pywikibot.output(str(page))
        except pywikibot.NoPage:
            return
        except pywikibot.IsRedirectPage:
            return

def is_person_article(text):
    """Vraca True ako deluje da ovo moze biti clanak o osobi, False u suprotnom"""
    for s in NOT_PERSON_MATCHES:
        if re.search(s, text, re.IGNORECASE | re.UNICODE) != None:
            return False
    return True

def is_template_providing_category(text):
    """Vraca True ako postoji template u ovom tekstu koji obezbedjuje kategoriju rodjenja"""
    for t in TEMPLATES_PROVIDING_CATEGORY:
        if ("{{" + t) in text:
            return True
    return False

def already_has_category(text):
    """Vraca True ako ovaj clanak vec ima kategoriju rodjenja"""
    return re.search(u"\[\[(категорија|kategorija):\s*(рођени|rođeni)", text, re.IGNORECASE | re.UNICODE) != None

def has_numbers(text):
    """Ispituje da li u tekstu, u delu koji pominje rec "rodjen" ima neki broj (u delu oko dva reda,
    tj. u tom pasusu). Ako nema nijednog broja, onda znaci da se rec "rodjen" ili koristi u nekom drugom
    kontekstu ("rodjen u kikindi", "rodjen mlad"...) ili da godina nije poznata.
    
    Vraca True ako postoji bilo kakav broj u takvom redu/pasusu, False u suprotnom
    """
    for to_search in POSITIVE_MATCHES:
        for match in re.findall(to_search, text, re.IGNORECASE | re.UNICODE):
            if re.search(".*[0-9].*", match) != None:
                return True
    return False

def main(*args):
    genFactory = pagegenerators.GeneratorFactory()

    for arg in pywikibot.handleArgs(*args):
        genFactory.handleArg(arg)

    gen = genFactory.getCombinedGenerator()
    gen = pagegenerators.PreloadingGenerator(gen)
    bot = GodineBot(gen)
    bot.run()

if __name__ == "__main__":
    try:
        main()
    finally:
        pywikibot.stopme()