David-Benjamin Kierdorf alias kristall hat ein Plugin für Gozerbot entwickelt. Wenn der Bot in einen IRC-Channel eingeloggt ist, dann werden alle Nachrichten in diesem Channel auf Nennung bestimmter deutscher Gesetze überprüft. Wird ein Gesetz erkannt, so wird versucht eine URL zu der genannten Norm zu finden und das Ergebnis wird dem Nutzer mitgeteilt. Zurückgegriffen wird auf das freie Angebot des BMJ "Gesetze im Internet" sowie auf den Juristischen Informationsdienst von dejure.org.

Das Programm steht unter der Creative Commons Lizenz Namensnennung-Keine kommerzielle Nutzung-Weitergabe unter gleichen Bedingungen 2.0 Deutschland.

Der Bot ist im JuraChat eingeloggt und kann dort ausprobiert werden.

Es gab vor Jahren bereits ein ähnliches Projekt (siehe Handakte vom 10.05.03). Beim JuraChatBot bestand die Besonderheit darin, dass die Muster zur Erkennung der Paragraphen auf einer offenen Wikiseite gepflegt werden konnten. Möglicherweise wäre das noch eine sinnvolle Erweiterung?

Quelltext

siehe auch auf dem Server des Autors: https://kristall.crew.c-base.org/code/index.html

   1 #!/ usr/bin/python
   2 # -*- coding: utf-8 -*-
   3 
   4 """ Einige Rechte vorbehalten. Dieser Code steht unter einer Creative Commons Namensnennung-Keine kommerzielle Nutzung-Weitergabe unter gleichen Bedingungen 2.0 Deutschland Lizenz. Author des Codes ist 'kristall aka D.-B. Kierdorf'. Für die Namensnennung ist 'kristall' ausreichend. Fragen, Anmerkungen, Kritik bitte an 'kristall 'ät' c-base.org'"""
   5 
   6 """ Dies ist ein 'plug in' für gozerbot 0.8 http://www.gozerbot.org ."""
   7 
   8 """ Import der benötigten Module."""
   9 from gozerbot.callbacks import callbacks
  10 from gozerbot.commands import cmnds
  11 
  12 import string, re, urllib
  13 
  14 from tokens import *
  15 from tokenizer import *
  16 
  17 """ Wenn der Bot in einen IRC-Channel eingeloggt ist, dann werden alle Nachrichten in diesem Channel auf Nennung bestimmter deutscher Gesetze überprüft. Wird ein bekanntes Gesetz genannt, so wird versucht eine URL zu der genannten Norm zu finden und das Ergebnis wird dem Nutzer mitgeteilt."""
  18 
  19 
  20 tokenizer = Tokenizer()
  21 """ Der 'tokenizer' ist die 'Schere' mit der die Nachrichten der Nutzer zerstückelt werden."""
  22 
  23 rA = load(open('/home/kristall/python/CBTC/cbtc.rA.unicode',"r"))
  24 """ 'rA' ist der reguläre Ausdruck der das 'Schnittmuster' für den Tokenizer enthält."""
  25 
  26 Gesetze = load(open('/home/kristall/python/CBTC/Gesetze.dict',"r"))
  27 """ 'Gesetze' ist ein python dict, das als Schlüssel Gesetze in juristischer Kurznotation verwendet. Der Wert eines Schlüssels ist der Titel des Gesetzes. Beispiel: {u'StGB': u'Strafgesetzbuch', u'BGB': 'Bürgerliches Gesetzbuch'}."""
  28 
  29 Parakette = [u'Abs.', u'Nr.', u'Satz', u'Urteilsformel', u'und', u'sowie', u'Rdn.', u'S.', u'Auslagenerstattung', u'Strafhöhe', u'm.w.N.', u'a.F.', u'n.F.', u'Urt.', u'I', u'II', u'III', u'IV', u'V', u'VI', u'VII', u'VIII', u'IX', u'X', u'XI', u'XII', u'XIII', u'XIV', u'XV', u'Nr.', u'a)', u'b)', u'c)', u'd)', u'e)', u'f)',u'g)', u'h)', u'a', u'b', u'c', u'd', u'e', u'f', u'g', u'h', u'i', u'j', u'k', u'(1)', u'(2)', u'(3)', u'(4)', u'(5)', u'(6)', u'(7)', u'(8)', u'(9)', u'(10)', u'(11)', u'(12)', u'(13)', u'(14)', u'(15)', u'(16)', u'(17)', u'(18)', u'(19)', u'(20)']
  30 """ 'Parakette' enthält Wörter die zwischen der Paragraphennummer und dem Gesetz stehen dürfen."""
  31 
  32 
  33 Probleme = {u'UStG': u'UStG_1980', u'AAG': u'AUFAG', u'A/KAE': u'KAEAANO', u'AAÜG-ÄndG': u'AAÜGÄndG', u'AbfKlärV': u'AbfKlärV_1992', u'AbfVerbrG': u'AbfVerbrG_2007', u'AbgrV': u'AbgrV_1985', u'ABV': u'BLGABV', u'ADNR': u'ADNR_2003', u'AO': u'AO_1977', u'ErbStG': u'ErbStG_1974', u'ErbStDV': u'ErbStDV_1998', u'GrStG': u'GrStG_1973', u'GrEStG': u'GrEStG_1983', u'UWG': u'UWG_2004'}
  34 """ Nicht alle Gesetze können per Regalanwendung aus ihrer Kurznotation in eine URL auf bundesrecht.juris.de übersetzt werden. 'Probleme' enthält als Schlüssel solche Gesetze. Der Wert eines Schlüssels enthält eine korrigierte Kurznotation. Dieses dict enthält nur einen kleinen Teil der Ausnahmen und kann bei Bedarf leicht (z.B. mit einem Script) erweitert werden werden."""
  35 
  36 
  37 def handle_nachricht(bot, ievent):
  38     """ Jede Nachricht in einem Channel in den der Bot eingeloggt ist 'triggert' diese Funktion. Die Funktion hat keinen Rückgabewert, sondern schickt gegebenenfalls die erzeugten Antworten an den Channel."""
  39     Antworten = erzeuge_Antworten(ievent.txt)
  40     """ 'Antworten' ist eine Liste. 'ievent.txt' enthält die Nachricht eines Nutzers."""
  41     for Antwort in Antworten:
  42 	ievent.reply(Antwort)
  43     """ Für jede Antwort in der Liste der Antworten: Sende die Antwort als Nachricht an den Channel.""" 
  44 
  45 def erzeuge_Antworten(Nachricht):
  46     """ Diese Funktion erzeugt die Antwortliste. Dazu wird die Nachricht zerstückelt, die Stücke markiert und die Markierungen ausgewertet. Dabei entsteht als Zwischenergebnis eine Liste aller genannten Normen. Beispiel: Nutzer: 'Also ich glaub das war § 823 II BGB iVm § 185 StGB, oder so ähnlich'; dann entsteht als Zwischenergebnis folgende Liste: ['§ 823 BGB', '§ 185 StGB']. Es wird dann versucht eine URL zu den Normen auf bundesrecht.juris.de und dejure.org zu finden. Außerdem wird der Titel zu den gefundenen Kurznotationen als Antwort angehängt. Rückgabewert ist eine (uU leere) Liste der Rückgabewerte der Funktionen 'existiert_NormURL_auf_bundesrecht(Norm)' und 'existert_NormURL_auf_dejure(Norm)', sowie dem Titel der Normen."""
  47     Antworten = []
  48     zu_testen = []
  49     TokenText = TextToken(Nachricht)
  50     TokenText = tokenizer.tokenize(TokenText, rA)
  51     TokenText = tagge_Tokens(TokenText)
  52     zu_testen = werte_Tags_aus(TokenText)
  53     for Test in zu_testen:
  54 	Antworten.append(existiert_NormURL_auf_bundesrecht(Test))
  55 	Antworten.append(existiert_NormURL_auf_dejure(Test))
  56 	Antworten.append(u'%s - %s' % (Test[-1], Gesetze[Test[-1]])) 
  57     #Antworten.append(TokenText['Lexeme'])
  58     return Antworten
  59 
  60 def tagge_Tokens(TokenText):
  61     """ Diese Funktion schaut sich jedes durch den Tokenizer erzeugte Textstückchen an und vergibt einen PosTag. Der Rückgabewert ist ein Kopie und keine Referenz."""
  62     Tok = TokenText.copy()
  63     for Token in Tok['Lexeme']:
  64 	if ((Token['Lexem'] == u'§') or (Token['Lexem'] == u'Art.') or (Token['Lexem'] == u'Artikel')): Token['PosTag'] = u'$Pp'
  65 	elif Token['Lexem'] == u'§§': Token['PosTag'] = u'§PP'
  66 	elif Token['Lexem'] in Parakette: Token['PosTag'] = u'PpK'
  67 	elif Token['Lexem'] in Gesetze: Token['PosTag'] = u'DtG'
  68     	else:
  69 	    try:
  70 		int(Token['Lexem'])
  71 		Token['PosTag'] = u'CARD'
  72 	    except: 
  73 		try:
  74 		    int(Token['Lexem'][:-1])
  75 		    Token['PosTag'] = u'CARDBK'
  76 		except:
  77 		    Token['PosTag'] = u'XY'
  78     return Tok
  79 
  80 def werte_Tags_aus(TokenText):
  81     """ Diese Funktion fildet mit Hilfe der PosTags mögliche Normnennungen und erzeugt die Zwischenergebnisliste für die Funktion 'erzeuge_Antworten(Nachricht)'. Rückgabewert ist eine (uU leere) Liste. """
  82     Sammelbox = []
  83     Ergebnis = []
  84     Bedingung01 = False
  85     Bedingung02 = True
  86     for Token in TokenText['Lexeme']:
  87 	if Token['PosTag'] == u'$Pp':
  88             if len(Sammelbox) != 0:
  89                 Sammelbox = []
  90                 Bedingung02 = True
  91             Sammelbox.append(Token['Lexem'])
  92             Bedingung01 = True
  93         elif ((u'CARD' in Token['PosTag']) and (Bedingung01)):
  94             if Bedingung02:
  95                 Sammelbox.append(Token['Lexem'])
  96                 Bedingung02 = False
  97         elif ((Token['PosTag'] == u'PpK') and (Bedingung01)):
  98             pass
  99         elif ((Token['PosTag'] == u'DtG') and (Bedingung01)):
 100 	    Sammelbox.append(Token['Lexem'])
 101 	    Ergebnis.append(Sammelbox)
 102 	    Antwort = []
 103             Bedingung01 = False
 104             Bedingung02 = True
 105         else:
 106             Bedingung01 = False
 107             Bedingung02 = True
 108             Sammelbox = []
 109     return Ergebnis
 110 
 111 def existiert_NormURL_auf_bundesrecht(Normliste):
 112     """ Diese Funktion verwandelt eine Norm in eine URL und testet die Existenz der konkreten Norm auf bundesrecht.juris.de, sollte die konkret genannte Norm nicht finden lassen, dann wird versucht zumindest den Index zu dem Gesetz zu finden. Sollte auch dies scheitern wird dies dem Nutzer mitgeteilt. Rückgabewert ist ein String."""
 113     url = u''
 114     Norm = Normliste[:]
 115     if Norm[-1] in Probleme:
 116 	Norm[-1] = Probleme[Norm[-1]]
 117     Norm[-1] = ersetze_Zeichen(Norm[-1])
 118     if u'§' in Norm[0]:
 119 	if u'.' in Norm[-1][1]: url = u'http://bundesrecht.juris.de/%s_%s/__%s.html' % (Norm[-1][3:].lower(), Norm[-1][0], Norm[1])
 120 	elif u'.' in Norm[-1][2]: url = u'http://bundesrecht.juris.de/%s_%s/__%s.html' % (Norm[-1][4:].lower(), Norm[-1][0:2], Norm[1])
 121 	else: url = u'http://bundesrecht.juris.de/%s/__%s.html' % (Norm[-1].lower(), Norm[1])
 122     else: url = u'http://bundesrecht.juris.de/%s/art_%s.html' % (Norm[-1].lower(), Norm[1])
 123     opener = urllib.FancyURLopener({})
 124     data = opener.open(url)
 125     site = unicode(data.read(), 'iso-8859-1')
 126     if u'404 Not Found' in site:
 127 	if u'.' in Norm[-1][1]: url = u'http://bundesrecht.juris.de/%s_%s/index.html' % (Norm[-1][3:].lower(), Norm[-1][0])
 128 	else: url = u'http://bundesrecht.juris.de/%s/index.html' % (Norm[-1].lower())
 129 	data = opener.open(url)
 130 	site = unicode(data.read(), 'iso-8859-15')
 131 	if u'404 Not Found' in site: return u'Kann leider weder die Norm noch den Index auf bundesrecht.juris.de finden.'
 132 	else: return u'Konkrete Norm nicht, aber %s gefunden.' % (url)
 133     return url
 134 
 135 def ersetze_Zeichen(worin, womit = u'_'):
 136     """ URLs dürfen eine Reihe von Zeichen nicht enthalten, auf bundesrecht.juris.de werden solche Zeichen durch '_' ersetzt. Diese Funktion ersetzt solche Zeichen durch Unterstriche. Rückgabewert ist ein String der '_' statt verbotener Zeichen enthält."""
 137     worin = worin.replace(u'Ä', womit)
 138     worin = worin.replace(u'Ö', womit)
 139     worin = worin.replace(u'Ü', womit)
 140     worin = worin.replace(u'ä', womit)
 141     worin = worin.replace(u'ö', womit)
 142     worin = worin.replace(u'ü', womit)
 143     worin = worin.replace(u'ß', womit)
 144     worin = worin.replace(u' ', womit)
 145     return worin
 146 
 147 
 148 def existiert_NormURL_auf_dejure(Normliste):
 149     """ Diese Funktion überprüft ob eine konkrete Norm auf dejure.org gefunden werden kann. Bei einem Fehlschlag wird auch hier geprüft, ob zumindest ein Index zu dem genannten Gesetz gefunden werden kann. Sollte nix gefunden werden wird keine Nachricht für den Nutzer erzeugt. Rückgabewert ist uU ein String. """
 150     Umlaute = [u'ä', u'ö', u'ü', u'Ä', u'Ö', u'Ü', u'ß']
 151     Norm = Normliste[:]
 152     for Umlaut in Umlaute:
 153 	if Umlaut in Norm[-1]: return
 154     url = u'http://dejure.org/gesetze/%s' % (Norm[-1])
 155     opener = urllib.FancyURLopener({})
 156     data = opener.open(url)
 157     site = unicode(data.read(), 'iso-8859-1')
 158     if u'404 Not Found' in site: return
 159     else:
 160 	url2 = u'%s/%s.html' % (url, Norm[-2])
 161 	data = opener.open(url2)
 162 	file = unicode(data.read(), 'iso-8859-1')
 163 	if u'existiert nicht' in file: return u'Index auf %s vorhanden.' % (url)
 164 	else: return url2
 165 
 166 callbacks.add('PRIVMSG', handle_nachricht, threaded=True)
 167 """ Für jede Nachricht in einem Channel rufe 'handle_nachricht()' auf."""
 168 
 169 """ Beispiel-Dialog:
 170 
 171 <Nutzer> Also dann testen wir mal den § 823 II BGB in Verbindung mit § 185 StGB.
 172 <Bot> http://bundesrecht.juris.de/bgb/__823.html
 173 <Bot> http://dejure.org/gesetze/BGB/823.html
 174 <Bot> BGB - Bürgerliches Gesetzbuch
 175 <Bot> http://bundesrecht.juris.de/stgb/__185.html
 176 <Bot> http://dejure.org/gesetze/StGB/185.html
 177 <Bot> StGB - Strafgesetzbuch
 178 """
lawurl.py

LawUrl (zuletzt geändert am 2008-01-20 19:55:32 durch anonym)