从 Wiki 中挖掘国与国之间的联系

wiki Jan 04, 2016

Wiki是一个众包性质的在线百科全书网站。志愿者们可以在上面编辑自己擅长领域的知识,它的宗旨是"中立的观点"。从某种程度上说,Wiki 和 OpenStreetMap 项目十分类似,只不过OpenStreetMap 项目只是专注于对空间数据的创建和编辑。

正是由于Wiki的众包特点,每个人都可以编辑页面,并且我们可以在页面之间创建链接。在Wiki里,可以通过一个特殊的URL区获得连接到某个页面的所有页面列表,比如,https://en.wikipedia.org/wiki/Special:WhatLinksHere/China 这个页面显示了所有可以链接到中国页面的链接列表。(由于中文维基已经被墙,这里访问的是英文维基)。

能否通过这个特殊的URL来挖掘国与国之间的联系呢?

通常,Wiki中一个国家的页面存在链接到另一国家的页面,说明这两个国家肯定有着一定的联系,比如可能是相邻关系、历史上有渊源、政治、经济或者是军事方面有联系等等。我们可以假设,如果某个国家被链接的次数越多,那么就有越多的国家和它有关系,也说明这个国家也就越重要。当然,这只是笼统地这么一说,国家的重要性是个很宽泛的话题,但是我们不妨先把国与国之间在Wiki上的链接关系找出来并可视化再说。

首先,我们要找到一个全世界所有国家在的列表,然后在Wiki里通过上述的URL去挖掘它们各自的联系。在Wiki里有一个国家ISO代码的页面,我们就从爬取这个页面的所有国家开始。下面的c++代码显示了如何用正则匹配去获得所有国家和地区的ISO代码和名称以及它们在Wiki中的链接地址(完整代码托管在oschina上):

std::string content;
if (!curl_get("https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#IN", content)) {
    return false;
}
// regex search
std::regex expression("<td id=\"[A-Z]{2}\"><span style=\"[^\"]*\">[A-Z]{2}</span></td>\n<td><a href=\"[^\"]*\" title=\"[^\"]*\">.*</a></td>");

std::sregex_iterator iter(content.cbegin(), content.cend(), expression);
std::sregex_iterator iter_end;
int count = 0;
for (; iter != iter_end; ++iter) {
    std::string searched_string = (*iter)[0].str();
    std::string code, url, name;
    // country code
    code = searched_string.substr(8, 2);
    if (!std::isupper(code[0]) || !std::isupper(code[1])) {
        std::cout << "code: " << code << " is invalid!\n";
    }
    // country url
    std::regex url_expresion("href=\"[^\"]*\" ");
    std::smatch match;
    if (std::regex_search (searched_string, match, url_expresion)) {
        std::string s = match[0].str();
        url = s.substr(6, s.length() - 8);
    }
    // country name
    std::regex name_expresion("title=\"[^\"]*\"");
    if (std::regex_search (searched_string, match, name_expresion)) {
        std::string s = match[0].str();
        name = s.substr(7, s.length() - 8);
    }
    // construct country
    Country country(code, name, url);
    this->countries_.push_back(country);
    this->url_countries_.emplace(std::make_pair(url, count++));
}

获得国家的列表后,便可以依次寻找每个国家被链接的页面列表:

for (size_t i = 0; i < countries_.size(); ++i) {
    Country& country = countries_[i];

    // get page with maximal links list
    std::string links_url = "https://en.wikipedia.org/wiki/Special:WhatLinksHere/" + country.get_url().substr(5);
    std::string links_page;
    if (!curl_get(links_url, links_page)) {
        continue;
    }
        
    // regex search country page
    std::regex expression("<li><a href=\"[^\"]*\" title=\"[^\"]*\">.*</a>  ‎ <span class=");
    std::sregex_iterator iter(links_page.cbegin(), links_page.cend(), expression);
    std::sregex_iterator iter_end;
    for (; iter != iter_end; ++iter) {
        std::string searched_string = (*iter)[0].str();
        std::regex url_expresion("href=\"[^\"]*\" ");
        std::smatch match;
        if (std::regex_search(searched_string, match, url_expresion)) {
            std::string s = match[0].str();
            std::string href = s.substr(6, s.length() - 8);
            int index = this->Search(href, URL);
            if (index != -1) {
                count++;
                country.AddLink(index);
            }
        }
    }
}

如果您对程序感兴趣,下载oschina上的代码编译运行,可以得到包含国与国之间联系的shapefile格式的文件,如果您不想运行程序,可以从百度云盘直接下载程序的输出文件。最后,借助 GeoHey 的数据上图,我们可以做出下面的地图出来:

单独看看在Wiki上可以链接到中国的国家:

从上图可以看出,除了周边的国家外,能够链接到中国的其他国家的地理分布还是比较均匀的,从这里可以体现出我国外交所作出的努力。另外,从太平洋的一系列能链接到中国的岛国的位置,依稀可见中国走出太平洋的地理路线。

为了更直观地看每个国家的链接数,采用气泡图的可视化方式:

从图中不难发觉,北美洲、西欧以及一些地理位置优越的岛国被链接次数较多。虽然可以链接到中国的国家不少(123个),但是这个数字基本属于中等偏上一点点。连接数前四甲分别是法国(197),加拿大(193),美国(189)以及英国(183)。

分析到这里,大家可能会怀疑中国的被链接次数为何会如此低。这里面有一个原因是我们访问的是英文的wiki,这些页面基本上都是英语国家创建和编辑的,如果是中文的wiki的话可能会有更多的链接指向中国。但是从另一方面来说,这能使我们摒除自己的偏见,更客观地认识中国与世界的其它国家的联系。

欢迎从GeoHey获取地理和位置相关的数据、知识、服务

访问网站 http://geohey.com

联系我们 contact@geohey.com

长按关注公众号

Atlas

To see what can we bring to the world.

评论正在加载...
Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.
分享