Python: Länder nach Kontinent aus Wikipedia abrufen

English Deutsch

Problem:

Du benötigst eine Liste von Ländern, geordnet nach Kontinent, unter einer freizügigen Lizenz.

Lösung

Eine Möglichkeit besteht darin, die Daten aus Wikipedia zu verwenden und die Informationen aus dem Wikitext-Format zu parsen. Beispielsweise bietet die englische Wikipedia „List of sovereign states and dependent territories by continent" eine gute Quelle.

Das hier bereitgestellte Skript lädt und parst dieses Format ohne externe Abhängigkeiten (nur Python-Kernbibliotheken). Python 2.7+ wird benötigt. Die Länderliste ist als Unicode kodiert.

Update 1.1 2015-12-14: Upgrade auf Python3, Datei-Header hinzugefügt Update 1.2 2017-02-19: Fehlerbehebung für geändertes Format

countries_by_continent.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Extrahiert eine Liste von Ländern, gruppiert nach Kontinent, aus Wikipedia
"""
__copyright__ = "Copyright (c) 2015 Uli Köhler"
__license__ = "Apache License v2.0"
__version__ = "1.2"

try:
    import urllib.request as urllib2
except ImportError:
    import urllib2
import re

def downloadWikipediaCountryList():
    """Lädt die Wikipedia-Länderliste im Wikitext-Format herunter"""
    url = "http://en.wikipedia.org/wiki/List_of_sovereign_states_and_dependent_territories_by_continent?action=raw"
    wikitext = urllib2.urlopen(url).read().decode("utf-8")
    return wikitext.split("\n")

def splitListAtIndices(theList, indices):
    """
    Teilt eine Liste an einer gegebenen Menge von Indizes
    >>> splitListAtIndices([1,3,5,7,9], [0, 3])
    [[], [1, 3, 5], [7, 9]]
    """
    return [theList[i:j] for i, j in zip([0] + indices, indices + [None])]

def extractContinents(wikitextLines):
    """Extrahiert bei einer Liste von Zeilen im Wikitext-Format die Zeilen, die zu einem Kontinent gehören, für jeden Kontinent"""
    continentRegex = re.compile("==\s*(\w+)\s*==")
    #Liste von (Zeilenindex, Kontinent)-Tupeln generieren
    continents = [(idx, continentRegex.match(line).group(1))
                  for idx, line in enumerate(wikitextLines) if continentRegex.match(line)]
    continentLines = splitListAtIndices(wikitextLines, [continent[0] for continent in continents])[1:]
    return {continents[i][1]: continentLines[i] for i in range(len(continents))}

countryRegex = re.compile("\| '+\[?\[?([^\]]+)\]?\]?\'+")
def findCountry(line):
    """
    >>> findCountry("| '''[[Germany]]'''")
    'Germany'
    >>> findCountry("| [[Berlin]]")
    """
    match = countryRegex.match(line)
    if match:
        country = match.group(1)
        if "De facto" in country:
            return None
        if "|" in country:
            return country.partition("|")[2]
        return country
    return None

def extractCountries(linesByContinent):
    return {continent: [findCountry(line) for line in continentLines if findCountry(line)]
            for continent, continentLines in linesByContinent.items()}


def getCountriesFromWikipedia():
    lines = downloadWikipediaCountryList()
    linesByContinent = extractContinents(lines)
    return extractCountries(linesByContinent)

if __name__ == "__main__":
    #Unit-Selftest
    import doctest
    doctest.testmod()
    #Länderliste ausgeben
    print(getCountriesFromWikipedia())

Check out similar posts by category: Python