Wikipedia:WikiProjekt Georeferenzierung/Archiv/GeoBot

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen

Hier eine Beschreibung, wie man sich einen GeoBot bastelt. Fehler dürfen gerne korrigiert werden, eure Patterns bitte ganz unten veröffentlichen, damit wir sie in einen zentralen Wikipedia:Bot integrieren können. GuidoD 18:39, 11. Jul 2005 (CEST)

Installation[Quelltext bearbeiten]

Zuerst mal braucht ihr ein relatives neues Python. Version 2.3 sollte hinreichen, besser 2.4 - die PyWikipedia-Macher sind nicht sehr gnädig mit alten Python-Installationen. Windows-Nutzer gehen bitte zu http://activestate.com/Products/ActivePython/ und holen sich ein aktuelles ActivePython. Das installiert/deinstalliert sich superleicht und bringt Alles mit.

Nächster Punkt ist http://pywikipediabot.sf.net - ich habe selbst die CVS-Version genutzt, einen Tarball kann man sich aber sicherlich aus der Release-Ecke holen. Wo man das auspackt, ist völlig egal. Wenn fertig, braucht ihr eine Kommandozeile, und nutzt "cd" um dorthin zu gehen.

(Hinweis: Windows-Nutzer bekommen sehr leicht Unix-Tools über http://x.cygwin.com - dort liegt eine setup.exe, mit deren Hilfe man sich einige hundert (!) Programme lokal installieren kann)

Jetzt muss man dem Baukasten noch beibringen, wie man sich einloggt.

Zu diesem Zweck legt man eine user-config.py datei an. Deren Format ist in config.py beschrieben. Im Wesentlichen müsste sie so aussehen:

mylang='de'
usernames['wikipedia']['de'] = 'guidod'
# usernames['wikipedia']['en'] = 'guidod'
# usernames['wikipedia']['test'] = 'guidod'
# usernames['wikipedia']['commons'] = 'guidod'

special_page_limit = 800

Anschließend ruft man einmalig login.py auf, und zwar mit dem Nutzernamen und Passwort.

python login.py -user:guidod -pass:***

Damit wird eine Datei login-data/de-*.py angelegt, in der das Passwort verschlüsselt einhalten ist. Anschließend kann sich der Bot selber einloggen. Das sollte man abschließend testen mit:

python test.py

Wir nutzen hier das Modul replace.py; dieses besitzt ein dutzend Optionen, die man von der Kommandozeile aus rufen kann - wollen wir aber gar nicht. Wir nutzen stattdessen Pythons ausgeprägte Fähigkeiten zur Erweiterung. Angelegt wird also eine neue Datei "replace-geo.py" mit folgendem Inhalt:

# /usr/bin/env python 
# -*- coding: utf-8 -*-
import replace
import wikipedia
 
geo_fixes = {
   'ppl' : {
     'regex': True,
     'msg' : { 'de': u'ersetzte bla bot' },
     'replacements' : {
       u"(Geokoordinate\\|)(\\d+)°\\s*(\\d+)'\\s*N,*(\d+)°\s*(\d+)'\s*O" :
       u"\\1\\2° \\3 N, \\4° \\5 O"
       } }
   'geonet': {
     'regex': True,
     'msg': {
       'de':u'geonet bot'
       },
     'replacements': {
       u"{{(Geokoordinate\\|[^{}|]*)_type:PPL\\|"
       +u"(\\d+)°\s*(\\d+)'\\s*00\\s*N\\s*(\\d+)°\\s*(\\d+)'\\s*00\\s*O}}" :
       u"{{\\1_type:city_region:DE|"
       +u"\\2° \\3' 00 N, \\4° \\5' 00 O}}"
       }
     }
   }
 
def set_geo_fixes():
  replace.fixes = geo_fixes
 
if __name__ == "__main__":
   set_geo_fixes()
   try:
       replace.main()
   finally:
       wikipedia.stopme()

Prinzipiell überschreiben wir hier die Templates in replace.py mit unseren eigenen. Anschließend kann man den Bot rennen lassen mit:

 python replace-geo.py "-fix:ppl" "-cat:Ort in Brandenburg"

wobei die letzte Angabe ansagt, worauf er arbeiten soll. Es gibt da verschiedene Aufrufvarianten, nicht nur Kategorie. Zum Austesten solltet ihr euch einen Artikel heraussuchen, und diesen dann so angeben:

 python replace-geo.py "-fix:geocity-1" "-page:Abstatt"

Keine Bange, der Bot arbeitet standardmäßig niemals automatisch - er lädt eine Seite, versucht die Ersetzung, und nur wenn sich ein Unterschied ergibt, dann zeigt der den Unterschied auf dem Kommandozeilen-Terminal an, und fragt "Ja, Nein, Alle". Bei Enter wäre "Nein". Also einfach aufrufen und schauen, ob der Bot das richtige ändern würde, wenn ihr ihn lassen würdet.

Stolpersteine sind:

  • Spezialzeichen der Regexe
niemals u"Koordinate|" sondern u"Koordinate\\|"
niemals u"[[Kategorie:XX]]" sondern u"\\[\\[Kategorie:XX\\]\\]"
  • Niemals Greedy arbeiten
vermeide ".*". Wenn zwei Koordinaten hinteinander stehen, wird alles dazwischenliegende verworfen. Wennschon, dann mit anti-stern arbeiten
also "{{Koordinate\\|[^{}]*}}"

Last not least, das release-geo.py braucht noch einen Kopfzeilen-Kommentar, wenn "°" Unicode-Zeichen enthalten sind. Das steht in jenem PEP, auf den in der Fehlermeldung verwiesen wird, falls man nicht dran denkt. Unter neueren Linux-Versionen werden Textdateien schon normal in utf-8 kodiert, daher steht im Beispiel:

 #  -*- coding : utf-8 -*-

Besser Bots nicht im user-account laufen lassen - besser, wir legen einen Wikipedia:Bot an, dessen Änderungen man ausblenden kann. Deshalb, die ausgetesten Patterns bitte hier posten - damit sie zentral eingepflegt werden können. Einfach einen eigenen --fix:typ wählen.

her damit...

   # ersetzt _type:PPL durch type:city_region:DE und formatiert Sichttext
   'geonet-1': {
     'regex': True,
     'msg': {
       'de':u'geonet bot'
       },
     'replacements': {
       u"{{(Geokoordinate\\|[^{}|]*)_type:PPL\\|"
       +u"(\\d+)°\s*(\\d+)'\\s*00\\s*N\\s*(\\d+)°\\s*(\\d+)'\\s*00\\s*O}}" :
       u"{{\\1_type:city_region:DE|"
       +u"\\2° \\3' 00 N, \\4° \\5' 00 O}}"
       }
     }
    # sucht aus Gemeinde-Infobox die Geographische Lage und
    # Einwohner heraus, fügt vor Kategorie {Geokoordinate} ein
   'geocity-1': {
     'regex': True,
     'msg': {
       'de':u'GeoBot: add GeoKoo type:city()'
       },
     'exceptions':  ['<nowiki>', '{Geokoordinate'],
     'replacements': {
       u"(?s)("
       +u"\\|\\s*\\[\\[Geografische Lage\\]\\]\\s*:\\s*\\|\\|\\s*"
       +u"(\\d+)°\\s*(\\d+)'\\s*n\\.\\s*Br\\.\\s*<br\\s*/?>"
       +u"\\s*(\\d+)°\\s*(\\d+)'\\s*ö\\.\\s*L\\..*"
       +u"\\|\\s*\\[\\[Einwohner\\]\\]\\s*:\\s*\\|\\|\\s*"
       +u"(\\d*)[ .]*(\\d+)"
       +u"(?:.(?!\\[\\[Kategorie:))*)" :
       u"\\1{{Geokoordinate|\\2_\\3_N_\\4_\\5_E_type:city(\\6\\7)_region:DE|"
       +u"\\2°&nbsp;\\3'&nbsp;N, \\4°&nbsp;\\5'&nbsp;O}}"
       }
     }
# Gleicher sinn wie geocity-1, aber erkennt mehr Varianten, und ist bei der
# Erkennung sicherer - vermutlich sogar ohne Einzelbestaetigung durchlaufen
'geocity-2': {
  'regex': True,
  'msg': {
    'de':u'GeoBot: add GeoKoo type:city()'
    },
  'exceptions':  ['<nowiki>','{Geokoordinate', '{geokoordinate'],
  'replacements': {
    u"(?s)("
    +u"\\|\\s*\\[\\[Geografische Lage\\]\\]\\s*:\\s*\\|\\|\\s*"
    +u"(?:{{Koordinate\\|[^\\|]*\\|\\s*)?"
    +u"(\\d+)°\\s*(\\d+)'\\s*(?:N,*|n\\.\\s*Br?\\.)\\s*"
    +u"(?:<br\\s*/?>\\s*)?"
    +u"(\\d+)°\\s*(\\d+)'\\s*(?:O,*|ö\\.\\s*L\\.)\\s*"
    +u"}*.*"
    +u"\\|\\s*\\[\\[Einwohner\\]\\]\\s*:\\s*\\|\\|\\s*"
    +u"(\\d*)[ .]*(\\d+)\\s*'*(?:\\||\\(|<\\w)"
    +u"(?:.*==)?(?:.*}})?(?:.(?!\\[\\[Kategorie:))*)(?=\\n\\[\\[Kategorie:)" :
    u"\\1\n{{Geokoordinate|\\2_\\3_N_\\4_\\5_E"
    +u"_type:city(\\6\\7)_region:DE|"
    +u"\\2°&nbsp;\\3'&nbsp;N, \\4°&nbsp;\\5'&nbsp;O}}"
    ,
    u"(?s)("
    +u"\\|\\s*\\[\\[Geografische Lage\\]\\]\\s*:\\s*\\|\\|\\s*"
    +u"(?:{{Koordinate\\|[^\\|]*\\|\\s*)?"
    +u"(\\d+),(\\d+)°\\s*(?:N,*|n\\.\\s*Br?\\.)\\s*"
    +u"(?:<br\\s*/?>\\s*)?"
    +u"(\\d+),(\\d+)°\\s*(?:O,*|ö\\.\\s*L\\.)\\s*"
    +u"}*.*"
    +u"\\|\\s*\\[\\[Einwohner\\]\\]\\s*:\\s*\\|\\|\\s*"
    +u"(\\d*)[ .]*(\\d+)\\s*'*(?:\\||\\(|<\\w)"
    +u"(?:.*==)?(?:.*}})?(?:.(?!\\[\\[Kategorie:))*)(?=\\n\\[\\[Kategorie:)" :
    u"\\1\n{{Geokoordinate|\\2.\\3_N_\\4.\\5_E"
    +u"_type:city(\\6\\7)_region:DE|"
    +u"\\2,\\3°&nbsp;N, \\4,\\5°&nbsp;O}}"
    ,
    u"(?s)("
    +u"\\|\\s*\\[\\[Geografische Lage\\]\\]\\s*:\\s*\\|\\|\\s*"
    +u"(?:{{Koordinate\\|[^\\|]*\\|\\s*)?"
    +u"(\\d+)°\\s*(\\d+)'\\s*(\\d+)\"\\s*(?:N,*|n\\.\\s*Br?\\.)\\s*"
    +u"(?:<br\\s*/?>\\s*)?"
    +u"(\\d+)°\\s*(\\d+)'\\s*(\\d+)\"\\s*(?:O,*|ö\\.\\s*L\\.)\\s*"
    +u"}*.*"
    +u"\\|\\s*\\[\\[Einwohner\\]\\]\\s*:\\s*\\|\\|\\s*"
    +u"(\\d*)[ .]*(\\d+)\\s*'*(?:\\||\\(|<\\w)"
    +u"(?:.*==)?(?:.*}})?(?:.(?!\\[\\[Kategorie:))*)(?=\\n\\[\\[Kategorie:)" :
    u"\\1\n{{Geokoordinate|\\2_\\3_\\4_N_\\5_\\6_\\7_E"
    +u"_type:city(\\8\\9)_region:DE|"
    +u"\\2°&nbsp;\\3'&nbsp;\\4\"&nbsp;N, \\5°&nbsp;\\6'&nbsp;\\7\"&nbsp;O}}"
    ,
    u"(?s)("
    +u"\\|\\s*\\[\\[Geografische Lage\\]\\]\\s*:\\s*\\|\\|\\s*"
    +u"(?:{{Koordinate\\|[^\\|]*\\|\\s*)?"
    +u"(\\d+)°\\s*(\\d+),(\\d+)'\\s*(?:N,*|n\\.\\s*Br?\\.)\\s*"
    +u"(?:<br\\s*/?>\\s*)?"
    +u"(\\d+)°\\s*(\\d+),(\\d+)'\\s*(?:O,*|ö\\.\\s*L\\.)\\s*"
    +u"}*.*"
    +u"\\|\\s*\\[\\[Einwohner\\]\\]\\s*:\\s*\\|\\|\\s*"
    +u"(\\d*)[ .]*(\\d+)\\s*'*(?:\\||\\(|<\\w)"
    +u"(?:.*==)?(?:.*}})?(?:.(?!\\[\\[Kategorie:))*)(?=\\n\\[\\[Kategorie:)" :
    u"\\1\n{{Geokoordinate|\\2_\\3.\\4_N_\\5_\\6.\\7_E"
    +u"_type:city(\\8\\9)_region:DE|"
    +u"\\2°&nbsp;\\3,\\4'&nbsp;N, \\5°&nbsp;\\6,\\7'&nbsp;O}}"
  }
}