【问题标题】:List all Wikipedia articles in one category and subcategories列出一个类别和子类别中的所有 Wikipedia 文章
【发布时间】:2014-02-01 11:13:49
【问题描述】:

有没有办法获得一个类别中所有维基百科文章的列表,包括所有子类别?

我尝试使用 PHP 脚本从类别页面中提取链接,但似乎无法获取包括子类别在内的所有文章。

【问题讨论】:

  • 这个问题似乎跑题了,因为它与编程无关。
  • 好的,抱歉,我尝试使用php脚本提取所有文章页面的链接,但似乎无法获取包括子类别在内的所有文章。
  • 编辑您的问题以反映这一点。它现在似乎与编程无关。
  • 这个创建所有页面/子类别页面的列表并将它们打印为 pdf 文件:github.com/produnis/myscripts/blob/master/PHP/mwc2pdf.php 您可能只想跳过打印部分...

标签: php wikipedia mediawiki-api


【解决方案1】:

您可以使用MediaWiki API,特别是list=categorymembers 来执行此操作。

这是一个随机的例子:

上面的链接将为您提供 XML 格式的 Category:Defunct airports in Prince Edward Island 中所有页面的列表(默认情况下,为了便于人类阅读,打印得很漂亮)。您可以通过在 URL 中附加适当的参数(例如 format=xmlformat=json)从各种机器可读的 output formats 中进行选择。

请注意,一般来说,上面显示的查询将包括该类别中的所有页面,包括文章和子类别。您可以通过包含参数cmnamespace=0 仅将其限制为文章,但是您将错过任何子类别。 (不过,您始终可以使用 cmnamespace=14 单独获取它们。)

您可能想要该信息的原因是 list=categorymembers 查询本身不会递归到子类别中,因此如果您需要,您必须自己做。但是,如果您这样做,请注意不要陷入任何类别循环,并确保对结果进行完整性检查 - 很容易从全子类遍历。

此外,默认情况下,单个 categorymembers 查询最多可为您提供 10 个结果。您可以通过在查询中包含参数 cmlimit=max 将限制增加到 500(或 5000,如果您碰巧可以访问 Wikipedia 上的 bot-flagged account),但即便如此,非常大的类别可能会被切断。如果发生这种情况,查询结果将包含一个 query continuation 部分,该部分将告诉您(或您的 MW API client library)如何使用其他查询获取其余页面。


编辑:我有点错过了您专门询问获取子类别中的文章的事实。这是一些基本(未经测试!)示例代码,说明如何使用Apibot 0.40 桥接接口(我只是随机选择的,因为它看起来像一个不错的 PHP MW API 客户端库,所以我不需要担心关于查询延续等细节):

function pages_under_category ( $category ) {
    global $bridge;  // I'll assume you've set this up in advance

    $queue = array( $category );  // categories to fetch
    $seen  = array( $category );  // categories already seen
    $pages = array();  // result pages (format: $title => array( $cat, ... ))

    while ( !empty( $queue ) ) {
        $cat = array_shift( $queue );

        $query = $bridge->query_list_categorymembers();
        $query->title = $cat;  // assume "Category:" prefix is included

        // fetch the contents of the category
        $query_result = $query->xfer();
        while ( $query_result ) {
            foreach ( $query->data as $page_data ) {

                $title = $page_data['title'];
                $namespace = $page_data['ns'];

                if ( $namespace == 0 ) {      // it's an article!
                    if ( !isset( $pages[$title] ) ) {
                        $pages[$title] = array();
                    }
                    $pages[$title][] = $cat;  // record where we found it
                }
                else if ( $namespace == 14 ) {  // it's a subcategory
                    if ( !in_array( $title, $seen ) ) {
                        $seen[] = $title;  // avoid loops!
                        $queue[] = $title;
                    }
                }
            }
            $query_result = $query->next();
        }
    }
    return $pages;
}

您可能想要添加到上面的代码中的一个功能是对结果大小/迭代次数的某种限制,因此即使递归检索以某种方式找到了它的方式,例如,Category:Contents,它也会在在某些时候停止尝试列出 Wikipedia 上的每一页。

【讨论】:

  • 谢谢!我将尝试在下周内对其进行测试。
【解决方案2】:

这可以通过 PetScan 完成,例如例如https://petscan.wmflabs.org/?psid=19820

您可以选择进入子类别的深度并添加搜索词和/或排除属于指定其他类别的页面。

【讨论】:

    猜你喜欢
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 2014-10-03
    相关资源
    最近更新 更多