在一个类别和子类别中列出所有Wikipedia文章

use*_*254 1 php wikipedia mediawiki-api

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

我试图使用PHP脚本从类别页面中提取链接,但是似乎不可能获得所有包括子类别的文章。

Ilm*_*nen 5

为此,您可以使用链接到MediaWiki API,具体list=categorymembers

这是一个随机的例子:

上面的链接将为您提供XML格式的爱德华王子岛的Category:Defunct机场中所有页面的列表(默认情况下,漂亮的页面易于打印)。通过将适当的参数(例如或)附加到URL,可以从多种机器可读的输出格式中进行选择。format=xmlformat=json

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

您可能需要该信息的原因是list=categorymembers查询本身不会递归到子类别,因此,如果需要,则必须自己执行。如果你这样做,不过,要小心,不要被逮住任何类别的循环,并确保你对结果做了仔细的检查-这是很容易得到的方式比你从满子遍历预期更多的网页。

另外,默认情况下,单个categorymembers查询最多可提供10个结果。通过在查询中包含参数,可以将该限制增加到500(如果您恰巧可以访问Wikipedia上具有机器人标记的帐户,则可以增加到5000 )cmlimit=max,但是即使那样,很大的类别也可能会被截断。如果发生这种情况,查询结果将包括查询继续部分,该部分将告诉您(或您的MW API客户端库)如何使用其他查询来获取其余页面。


编辑:我有点想念一个事实,即您是专门询问有关在子类别中获取文章的。这是一些基本的(未经测试!)示例代码,说明如何使用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;
}
Run Code Online (Sandbox Code Playgroud)

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