Python:从 Wikipedia 按大洲获取国家

问题:

你需要一个按大洲排序的国家列表,在宽松许可下。

解决方案

一种可能性是使用 Wikipedia 的数据并从 Wikitext 格式解析信息。例如,英文维基百科"按大洲排列的主权国家和附属领土列表"提供了很好的来源。

此处提供的脚本无需任何外部依赖(仅 Python 核心库)即可下载和解析该格式。需要 Python 2.7+。国家列表以 Unicode 编码。

更新 1.1 2015-12-14: 升级到 Python3,添加文件头 更新 1.2 2017-02-19: 修复更改的格式

countries_by_continent.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
从 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():
    """以 wikitext 格式下载 wikipedia 国家列表"""
    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):
    """
    在给定的一组索引处分割列表
    >>> 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):
    """给定 wikitext 格式的行列表,为每个大洲提取属于该大洲的行"""
    continentRegex = re.compile("==\s*(\w+)\s*==")
    #生成(行索引,大洲)元组列表
    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__":
    #单元自测
    import doctest
    doctest.testmod()
    #打印国家列表
    print(getCountriesFromWikipedia())

Check out similar posts by category: Python