Php 如何获得复杂维基百科模板的结果?

Php 如何获得复杂维基百科模板的结果?,php,parsing,mediawiki,wikipedia,Php,Parsing,Mediawiki,Wikipedia,这是一个有点难理解的问题,但我会尽我所能解释它。首先,让我介绍一个示例页面: 这是一个维基百科页面,特别是一个物种页面,因为它的右边有“taxobox”。我正在尝试使用PHP解析taxobox中的属性。在维基百科中,有两种方法可以创建这样的taxobox:手动创建,或者使用特殊的“自动taxobox”模板创建 我可以解析手动的。我使用Wikipedia的API以json格式返回页面内容,然后使用一些正则表达式获取这些属性 但是,对于自动taxobox,返回的内容如下所示: > {{aut

这是一个有点难理解的问题,但我会尽我所能解释它。首先,让我介绍一个示例页面:

这是一个维基百科页面,特别是一个物种页面,因为它的右边有“taxobox”。我正在尝试使用PHP解析taxobox中的属性。在维基百科中,有两种方法可以创建这样的taxobox:手动创建,或者使用特殊的“自动taxobox”模板创建

我可以解析手动的。我使用Wikipedia的API以json格式返回页面内容,然后使用一些正则表达式获取这些属性

但是,对于自动taxobox,返回的内容如下所示:

> {{automatic taxobox | name = African Bush Elephant<ref
> name=MSW3>{{MSW3 Proboscidea | id = 11500009 | page =
> 91}}</ref> | status = VU | status_system = iucn3.1 | status_ref
> = <ref name=IUCN>{{IUCN2010|assessors=Blanc, J.|year=2008|version=2010.1|id=12392|title=Loxodonta
> africana|downloaded=04 April 2010}}</ref> | trend = unknown |
> image = African Bush Elephant.jpg | taxon = Loxodonta africana |
> synonyms = ''Loxodonta africana africana'' | binomial = ''Loxodonta
> africana'' | binomial_authority = ([[Johann Friedrich
> Blumenbach|Blumenbach]], 1797) }}
如果您将其与Wikipedia上的实际页面进行比较,您会发现缺少几个属性。例如,属性“Kingdom”在真实页面上可见,但在此处不返回。还有更多的财产像那样丢失了

这与模板需要Wikipedia的服务器端命令将模板转换为实际输出类似。我了解到API有一个“expandtemplates”操作,您可以发送一个类似于上面的代码段,您将得到用户看到的结果。我在几个模板中使用了它,它可以工作,但不幸的是,它不适用于自动taxobox模板。单击此链接查看expandtemplates返回的内容:

如您所见,模板实际上并没有展开。相反,它显示更多的模板,嵌套并重复多次


因此,现在我一直在尝试从具有auto taxobox模板的页面读取这些属性。我唯一能想到的另一个方向是不使用API,只解析实际页面的html。这对于某些属性是可行的,但其他属性的解析非常脆弱

使用
action=parse
而不是
action=expandtemplates
。正如您所注意到的,
expandtemplates
只扩展一个级别;此外,它不会完全预处理输入(例如,它不会成功地处理模板内的某些变量引用)。

与其重新设计轮子,不如检查,它已经从Wikipedia模板中提取了所有可能的内容,并以各种易于解析的格式公开了它。

这是一段php模板解析代码

目标是创建一个如下所示的数组($data):

$data[页面名称]=数组(key1=>val1,key2=>val2


你需要什么信息?从代码的快速检查来看,它看起来相当简单friendly@Nanne:我基本上需要taxobox中的所有属性,这意味着作为用户通常会看到的所有属性。问题不是从输出中获取值,而是缺少几个值。您在页面上看到但未在expandtemplates结果集中返回的属性。是否需要将其递归发送到expandtemplates,直到输出中没有未展开的模板?@Martin。我也是这么想的。您可以通过复制上述链接的结果集并将其粘贴到url中的“text=”之后来尝试。它似乎只返回了原始内容的半断开的第一行。在扩展版本中,我没有看到任何模板,只是表的wiki语法。谢谢,我不知道该操作。虽然结果很难解析,但总比没有数据好:)是的。。。维基百科的信息框主要是为了显示而设计的,而不是为了便于解析。那么最终的URL是什么呢?如果我只是想用泰索博克斯治疗金黄色葡萄球菌,我该怎么做?好建议。我以前确实查看过dbpedia,但它不符合我的需要。dbpedia主要以文章级别的粒度提取元数据(infobox的参数、类别)。这对一些需要关注文章模板的特殊任务没有帮助,比如获取书目内容的引用书模板,或者将其从维基百科的一个版本翻译成另一个版本。
    $namespaceNames = "";
    $data = array();
    $sql_conn = array();

    $query = "select * from templatelinks left join page on templatelinks.tl_from=page.page_id where tl_title='speciesbox' order by page_title;";

    $sql_conn = mysql_connect('localhost', 'root', 'password');
    mysql_select_db('my_wiki');

    $result = mysql_query($query, $sql_conn);

    while($row = mysql_fetch_object($result))
    {
            $q2 = "select rev_text_id from revision where rev_page=".$row->page_id." order by rev_timestamp desc limit 1";
            if(($res2 = mysql_query($q2)) && ($row2 = mysql_fetch_object($res2)))
            {
                    $q3 = "select * from text where old_id=".$row2->rev_text_id;
                    if(($res3 = mysql_query($q3)) && ($row3 = mysql_fetch_object($res3)))
                    {
                        preg_match_all('/\{\{(?:[^{}]|(?R))*}}/', $row3->old_text, $info);

                        $kvs = explode( "|", substr($info[0][0], 0, strlen($info[0][0])-2));

                        $item = array();

                        foreach($kvs as $kv)
                        {
                                $kv = trim($kv);
                                if($kv == "") continue;
                                $eq = strpos($kv, "=");
                                if($eq === false) continue;
                                $key = trim(substr($kv, 0, $eq));
                                $val = trim(substr($kv, $eq+1));
                                $item[$key] = $val;
                        }
                        if(sizeof($item) > 0)
                        {
                               $title = str_replace("_", " ", $row->page_title);
                               $data[$title] = $item;
                        }
                   }
             }
        }


        foreach($data as $page=>$item)
        {

        }