Benutzer:Klexibot/Skripte: Unterschied zwischen den Versionen
Aus Klexikon – das Kinderlexikon
(+Logbuch, +Kleinigkeiten) |
(+besseres Logbuch, +Testlauf-Option, +Kleinigkeiten) |
||
Zeile 6: | Zeile 6: | ||
import locale | import locale | ||
import datetime | import datetime | ||
# dryrun = True # Ausgabe des Logbuchs in der Konsole ohne Änderungen am Klexikon | |||
dryrun = False # Änderungen werden direkt im Klexikon gespeichert. | |||
# Verwende deutsches Zahlenformat mit Tausenderpunkt und Dezimalkomma | # Verwende deutsches Zahlenformat mit Tausenderpunkt und Dezimalkomma | ||
Zeile 12: | Zeile 15: | ||
# Zuordnung von Wikidata-Abfrage-Feldern zu Vorlage-Parametern | # Zuordnung von Wikidata-Abfrage-Feldern zu Vorlage-Parametern | ||
fieldmap = { | fieldmap = { | ||
'Name': 'itemLabel', | |||
'Flagge': 'safeFlaggenDatei', | |||
'Hauptstadt': 'hauptstaedte', | |||
'Amtssprache': 'amtssprachen', | |||
'Staatsoberhaupt': 'oberhaeupter', | |||
'Einwohnerzahl': 'max_ew_in_mio', | |||
'Fläche': 'max_flaeche_rund', | |||
'Lagekarte': 'safeKartenDatei', | |||
'Lagebeschreibung': 'kontinente' | |||
} | } | ||
# Legt fest, welche Länder-Artikel bzw. Vorlagen-Parameter Klexibot nicht ändern soll | # Legt fest, welche Länder-Artikel bzw. Vorlagen-Parameter Klexibot nicht ändern soll | ||
blacklist = { | blacklist = { | ||
'Eidgenossenschaft', | |||
'Deutsches Kaiserreich', | |||
'Schottland', | |||
'Wales' | |||
} | } | ||
# Parameter aus dieser Liste werden nur gefüllt, falls bisher kein Wert enthalten war | # Parameter aus dieser Liste werden nur gefüllt, falls bisher kein Wert enthalten war | ||
preserved_values = { | preserved_values = { | ||
'Lagekarte', | |||
'Lagebeschreibung' | |||
} | } | ||
Zeile 44: | Zeile 47: | ||
with open('infobox_data_query.rq', 'r') as query_file: qry = query_file.read() | with open('infobox_data_query.rq', 'r') as query_file: qry = query_file.read() | ||
r = requests.get(url, params = {'format': 'json', 'query': qry }, headers = { | r = requests.get(url, params = {'format': 'json', 'query': qry }, headers = { | ||
'User-Agent':f'{requests.utils.default_headers()["User-Agent"]} (Klexikon bot by User:Tkarcher)'}) | |||
data = r.json() | data = r.json() | ||
# Initialisiere | # Initialisiere Logbuch-Eintrag | ||
logheader = f'== | logheader = f'== Logbuch vom {datetime.datetime.now().strftime("%c")} ==\n' | ||
newloghead = '=== Neu angelegte Infoboxen ===\n' | |||
newlogdata = '' | |||
chgloghead = '=== Änderungen an bestehenden Infoboxen ===\n' + \ | |||
'{| class="wikitable sortable"\n! Vorlage\n! Eigenschaft\n! Alter Wert\n! Neuer Wert\n' | |||
chglogdata = '' | |||
chglogfoot = '|}\n\n' | |||
# Gehe Wikidata-Tabelle Zeile für Zeile durch | # Gehe Wikidata-Tabelle Zeile für Zeile durch | ||
for item in data['results']['bindings']: | for item in data['results']['bindings']: | ||
title = item['titel_im_klexikon']['value'] | |||
# Ignoriere Artikel, die in der Ausschlußliste enthalten sind | |||
if title not in blacklist: | |||
# Öffne Vorlagen-Seite oder lege sie neu an | |||
page = pywikibot.Page(site, f'Vorlage:Infobox_{title}') | |||
code = mwparserfromhell.parse(page.text) | |||
# Ersetze Seiteninhalt mit {{Infobox Land}}, falls nicht vorhanden | |||
if not code.filter_templates(matches = lambda n: n.name.matches ('Infobox Land')): | |||
code = mwparserfromhell.parse('{{Infobox Land\n}}') | |||
newlogdata += f'* [[Vorlage:Infobox {title}]]\n' | |||
# Fülle alle Vorlagen-Felder | |||
for prop, field in fieldmap.items(): | |||
# Ignoriere Vorlagen-Parameter, die leer oder in der Ausschlußliste enthalten sind | |||
if field in item and f'{title}:{prop}' not in blacklist: | |||
# Ignoriere auch Parameter, die nicht überschrieben werden sollen | |||
if not ( | |||
prop in preserved_values and | |||
code.filter_templates()[0].has(prop) and | |||
code.filter_templates()[0].get(prop).value.strip() != ''): | |||
oldval = code.filter_templates()[0].get(prop).value.strip() if code.filter_templates()[0].has(prop) else '' | |||
val = item[field]['value'] | |||
if prop == 'Einwohnerzahl': | |||
ew = float(val) | |||
if ew > 1: | |||
val = f'etwa {locale.format_string("%.0f", ew, grouping = True)} [[Million]]en' | |||
else: | |||
val = f'etwa {locale.format_string("%.0f", ew * 1000000, grouping = True)}' | |||
elif prop == 'Fläche': | |||
val = f'etwa {locale.format_string("%i", int(val), grouping = True)} [[Meter|Quadratkilometer]]' | |||
elif prop == 'Staatsoberhaupt': | |||
if 'oberhaupt_bezeichnung' in item: | |||
val = f'{item["oberhaupt_bezeichnung"]["value"]} {val}' | |||
elif prop == 'Lagebeschreibung': | |||
val = f'Wo das Land in {val} liegt' | |||
# Speichere die Änderung nur, wenn sie aus mehr besteht als | |||
# einer geänderten Sortierreihenfolge in der Auslistung | |||
# (SPARQL 1.1 erlaubt kein ORDER BY in GROUP_CONCATs) | |||
if sorted (val) != sorted (oldval): | |||
code.filter_templates()[0].add (f' {prop} ', f' {val}\n', preserve_spacing = False) | |||
if not newlogdata.endswith (f'* [[Vorlage:Infobox {title}]]\n'): | |||
chglogdata += f'|- \n| [[Vorlage:Infobox {title}]]\n| {prop}\n| {oldval}\n| {val}\n' | |||
# Speichere die Änderungen, falls vorhanden, und verschiebe | |||
# Artikel ggf. zurück in Kategorie "ungeprüfte Infobox" | |||
if (page.text != str(code)) and not dryrun: | |||
# Speichere Vorlage | |||
page.text = str(code) | |||
page.save('Automatische Anlage der Länder-Infobox') | |||
# Öffne Länderartikel | |||
page = pywikibot.Page(site, title) | |||
code = mwparserfromhell.parse(page.text) | |||
# Binde Länder-Infobox ein, falls noch nicht geschehen | |||
# Mit "_" und " " wegen https://github.com/earwig/mwparserfromhell/issues/216 | |||
if not code.filter_templates(matches = lambda n: | |||
n.name.matches ({f'Infobox_{title}', f'Infobox {title}'})): | |||
code = mwparserfromhell.parse(f'{{{{Infobox_{title}}}}}\n{str(code)}') | |||
# Lösche [[Kategorie:Artikel mit geprüfter Infobox]], falls vorhanden | |||
if '[[Kategorie:Artikel mit geprüfter Infobox]]' in str(code): | |||
code.remove ('[[Kategorie:Artikel mit geprüfter Infobox]]') | |||
# Füge [[Kategorie:Artikel mit ungeprüfter Infobox]] ein, falls noch nicht geschehen | |||
if '[[Kategorie:Artikel mit ungeprüfter Infobox]]' not in str(code): | |||
code.append ('\n[[Kategorie:Artikel mit ungeprüfter Infobox]]') | |||
# Speichere Länderartikel | |||
page.text = str(code) | |||
page.save('Automatische Einbindung der Länder-Infobox') | |||
# Dokumentiere Änderungen in Logbuch | # Dokumentiere Änderungen in Logbuch | ||
page = pywikibot.Page(site, 'Benutzer:Klexibot/Logbuch') | log = \ | ||
page.text += | logheader + \ | ||
page.save('Logbuch aktualisiert') | newloghead + (newlogdata if newlogdata != '' else 'Es wurden keine neuen Infoboxen angelegt.\n') + \ | ||
chgloghead + (chglogdata if chglogdata != '' else '|- \n| colspan=4 | Es wurden keine bestehenden Daten geändert.\n') + chglogfoot | |||
if dryrun: | |||
print (log) | |||
else: | |||
page = pywikibot.Page(site, 'Benutzer:Klexibot/Logbuch') | |||
page.text += log | |||
page.save('Logbuch aktualisiert') | |||
</syntaxhighlight> | </syntaxhighlight> |
Version vom 12. April 2019, 21:39 Uhr
Skript zur Aktualisierung der Länder-Infoboxen
import requests
import pywikibot
import mwparserfromhell
import locale
import datetime
# dryrun = True # Ausgabe des Logbuchs in der Konsole ohne Änderungen am Klexikon
dryrun = False # Änderungen werden direkt im Klexikon gespeichert.
# Verwende deutsches Zahlenformat mit Tausenderpunkt und Dezimalkomma
locale.setlocale(locale.LC_ALL, 'german')
# Zuordnung von Wikidata-Abfrage-Feldern zu Vorlage-Parametern
fieldmap = {
'Name': 'itemLabel',
'Flagge': 'safeFlaggenDatei',
'Hauptstadt': 'hauptstaedte',
'Amtssprache': 'amtssprachen',
'Staatsoberhaupt': 'oberhaeupter',
'Einwohnerzahl': 'max_ew_in_mio',
'Fläche': 'max_flaeche_rund',
'Lagekarte': 'safeKartenDatei',
'Lagebeschreibung': 'kontinente'
}
# Legt fest, welche Länder-Artikel bzw. Vorlagen-Parameter Klexibot nicht ändern soll
blacklist = {
'Eidgenossenschaft',
'Deutsches Kaiserreich',
'Schottland',
'Wales'
}
# Parameter aus dieser Liste werden nur gefüllt, falls bisher kein Wert enthalten war
preserved_values = {
'Lagekarte',
'Lagebeschreibung'
}
# Anmeldung beim Klexikon
site = pywikibot.Site()
# Lade Wikidata-Tabelle und speichere sie in "data"-Variable
url = 'https://query.wikidata.org/sparql'
with open('infobox_data_query.rq', 'r') as query_file: qry = query_file.read()
r = requests.get(url, params = {'format': 'json', 'query': qry }, headers = {
'User-Agent':f'{requests.utils.default_headers()["User-Agent"]} (Klexikon bot by User:Tkarcher)'})
data = r.json()
# Initialisiere Logbuch-Eintrag
logheader = f'== Logbuch vom {datetime.datetime.now().strftime("%c")} ==\n'
newloghead = '=== Neu angelegte Infoboxen ===\n'
newlogdata = ''
chgloghead = '=== Änderungen an bestehenden Infoboxen ===\n' + \
'{| class="wikitable sortable"\n! Vorlage\n! Eigenschaft\n! Alter Wert\n! Neuer Wert\n'
chglogdata = ''
chglogfoot = '|}\n\n'
# Gehe Wikidata-Tabelle Zeile für Zeile durch
for item in data['results']['bindings']:
title = item['titel_im_klexikon']['value']
# Ignoriere Artikel, die in der Ausschlußliste enthalten sind
if title not in blacklist:
# Öffne Vorlagen-Seite oder lege sie neu an
page = pywikibot.Page(site, f'Vorlage:Infobox_{title}')
code = mwparserfromhell.parse(page.text)
# Ersetze Seiteninhalt mit {{Infobox Land}}, falls nicht vorhanden
if not code.filter_templates(matches = lambda n: n.name.matches ('Infobox Land')):
code = mwparserfromhell.parse('{{Infobox Land\n}}')
newlogdata += f'* [[Vorlage:Infobox {title}]]\n'
# Fülle alle Vorlagen-Felder
for prop, field in fieldmap.items():
# Ignoriere Vorlagen-Parameter, die leer oder in der Ausschlußliste enthalten sind
if field in item and f'{title}:{prop}' not in blacklist:
# Ignoriere auch Parameter, die nicht überschrieben werden sollen
if not (
prop in preserved_values and
code.filter_templates()[0].has(prop) and
code.filter_templates()[0].get(prop).value.strip() != ''):
oldval = code.filter_templates()[0].get(prop).value.strip() if code.filter_templates()[0].has(prop) else ''
val = item[field]['value']
if prop == 'Einwohnerzahl':
ew = float(val)
if ew > 1:
val = f'etwa {locale.format_string("%.0f", ew, grouping = True)} [[Million]]en'
else:
val = f'etwa {locale.format_string("%.0f", ew * 1000000, grouping = True)}'
elif prop == 'Fläche':
val = f'etwa {locale.format_string("%i", int(val), grouping = True)} [[Meter|Quadratkilometer]]'
elif prop == 'Staatsoberhaupt':
if 'oberhaupt_bezeichnung' in item:
val = f'{item["oberhaupt_bezeichnung"]["value"]} {val}'
elif prop == 'Lagebeschreibung':
val = f'Wo das Land in {val} liegt'
# Speichere die Änderung nur, wenn sie aus mehr besteht als
# einer geänderten Sortierreihenfolge in der Auslistung
# (SPARQL 1.1 erlaubt kein ORDER BY in GROUP_CONCATs)
if sorted (val) != sorted (oldval):
code.filter_templates()[0].add (f' {prop} ', f' {val}\n', preserve_spacing = False)
if not newlogdata.endswith (f'* [[Vorlage:Infobox {title}]]\n'):
chglogdata += f'|- \n| [[Vorlage:Infobox {title}]]\n| {prop}\n| {oldval}\n| {val}\n'
# Speichere die Änderungen, falls vorhanden, und verschiebe
# Artikel ggf. zurück in Kategorie "ungeprüfte Infobox"
if (page.text != str(code)) and not dryrun:
# Speichere Vorlage
page.text = str(code)
page.save('Automatische Anlage der Länder-Infobox')
# Öffne Länderartikel
page = pywikibot.Page(site, title)
code = mwparserfromhell.parse(page.text)
# Binde Länder-Infobox ein, falls noch nicht geschehen
# Mit "_" und " " wegen https://github.com/earwig/mwparserfromhell/issues/216
if not code.filter_templates(matches = lambda n:
n.name.matches ({f'Infobox_{title}', f'Infobox {title}'})):
code = mwparserfromhell.parse(f'{{{{Infobox_{title}}}}}\n{str(code)}')
# Lösche [[Kategorie:Artikel mit geprüfter Infobox]], falls vorhanden
if '[[Kategorie:Artikel mit geprüfter Infobox]]' in str(code):
code.remove ('[[Kategorie:Artikel mit geprüfter Infobox]]')
# Füge [[Kategorie:Artikel mit ungeprüfter Infobox]] ein, falls noch nicht geschehen
if '[[Kategorie:Artikel mit ungeprüfter Infobox]]' not in str(code):
code.append ('\n[[Kategorie:Artikel mit ungeprüfter Infobox]]')
# Speichere Länderartikel
page.text = str(code)
page.save('Automatische Einbindung der Länder-Infobox')
# Dokumentiere Änderungen in Logbuch
log = \
logheader + \
newloghead + (newlogdata if newlogdata != '' else 'Es wurden keine neuen Infoboxen angelegt.\n') + \
chgloghead + (chglogdata if chglogdata != '' else '|- \n| colspan=4 | Es wurden keine bestehenden Daten geändert.\n') + chglogfoot
if dryrun:
print (log)
else:
page = pywikibot.Page(site, 'Benutzer:Klexibot/Logbuch')
page.text += log
page.save('Logbuch aktualisiert')