php - 列出一个类别和子类别中的所有维基百科文章

标签 php wikipedia mediawiki-api

有什么方法可以得到一个类别中所有维基百科文章的列表,包括所有子类别?

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

最佳答案

您可以使用 MediaWiki API 执行此操作, 具体来说 list=categorymembers .

这是一个随机的例子:

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

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

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

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


编辑:我有点想念您专门询问有关获取子类别文章的事实。这是一些基本的(未经测试的!)示例代码,说明如何使用 Apibot 0.40 执行此操作桥接口(interface)(我只是随机选择的,因为它看起来像一个不错的 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。 , 它会在某个时候停止尝试列出维基百科上的每一页。

关于php - 列出一个类别和子类别中的所有维基百科文章,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21497323/

相关文章:

php - 为什么 eclipse 不能运行我的 php 文件?

MediaWiki API : How to get a list of newly created pages?

api - 反向维基百科地理标记查找

mediawiki - 较低的 MediaWiki 页面修订 ID 是否总是意味着较早的编辑?

php - 如何使用mysql顺序更新数据库

php - Laravel - 通过关系对象的属性对集合数组进行排序

php - 使用 php 表单将值存储到数据库中

json - 在 Bulbapedia 等自定义 wiki 上使用 Wikipedia API

api - 如何检索维基词典的单词内容?

wikipedia - 以编程方式检索所有维基百科语言的列表