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