Как разобрать XML Википедии с помощью PHP?

Как разобрать XML Википедии с помощью PHP? Пробовал с SimplePie, но ничего не вышло. Вот ссылка, по которой я хочу получить свои данные.

http://en.wikipedia.org/w/api.php?action=query&generator=allpages&gaplimit=2&gapfilterredir=nonredirects&gapfrom=Re&prop=revisions&rvprop=content&format=xml

Изменить код:

<?php
    define("EMAIL_ADDRESS", "[email protected]"); 
    $ch = curl_init(); 
    $cv = curl_version(); 
    $user_agent = "curl ${cv['version']} (${cv['host']}) libcurl/${cv['version']} ${cv['ssl_version']} zlib/${cv['libz_version']} <" . EMAIL_ADDRESS . ">"; 
    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent); 
    curl_setopt($ch, CURLOPT_COOKIEFILE, "cookies.txt"); 
    curl_setopt($ch, CURLOPT_COOKIEJAR, "cookies.txt"); 
    curl_setopt($ch, CURLOPT_ENCODING, "deflate, gzip, identity"); 
    curl_setopt($ch, CURLOPT_HEADER, FALSE); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 
    curl_setopt($ch, CURLOPT_HTTPGET, TRUE); 
    curl_setopt($ch, CURLOPT_URL, "http://en.wikipedia.org/w/api.php?action=query&generator=allpages&gaplimit=2&gapfilterredir=nonredirects&gapfrom=Re&prop=revisions&rvprop=content&format=xml"); 
    $xml = curl_exec($ch); 
    $xml_reader = new XMLReader(); 
    $xml_reader->xml($xml, "UTF-8"); 
    echo $xml->api->query->pages->page->rev;
?>

person yuli chika    schedule 29.01.2011    source источник


Ответы (3)


Обычно я использую комбинацию CURL и XMLReader для анализа XML, сгенерированного API Медиавики.

Обратите внимание, что вы должны указать свой адрес электронной почты в заголовке User-Agent, иначе скрипт API ответит HTTP 403 Forbidden.

Вот как я инициализирую дескриптор CURL:

define("EMAIL_ADDRESS", "[email protected]");
$ch = curl_init();
$cv = curl_version();
$user_agent = "curl ${cv['version']} (${cv['host']}) libcurl/${cv['version']} ${cv['ssl_version']} zlib/${cv['libz_version']} <" . EMAIL_ADDRESS . ">";
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookies.txt");
curl_setopt($ch, CURLOPT_COOKIEJAR, "cookies.txt");
curl_setopt($ch, CURLOPT_ENCODING, "deflate, gzip, identity");
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

Затем вы можете использовать этот код, который захватывает XML и создает новый объект XMLReader в $xml_reader:

curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
curl_setopt($ch, CURLOPT_URL, "http://en.wikipedia.org/w/api.php?action=query&generator=allpages&gaplimit=2&gapfilterredir=nonredirects&gapfrom=Re&prop=revisions&rvprop=content&format=xml");
$xml = curl_exec($ch);
$xml_reader = new XMLReader();
$xml_reader->xml($xml, "UTF-8");

EDIT: Вот рабочий пример:

<?php
define("EMAIL_ADDRESS", "[email protected]");
$ch = curl_init();
$cv = curl_version();
$user_agent = "curl ${cv['version']} (${cv['host']}) libcurl/${cv['version']} ${cv['ssl_version']} zlib/${cv['libz_version']} <" . EMAIL_ADDRESS . ">"; 
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookies.txt");
curl_setopt($ch, CURLOPT_COOKIEJAR, "cookies.txt");
curl_setopt($ch, CURLOPT_ENCODING, "deflate, gzip, identity");
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
curl_setopt($ch, CURLOPT_URL, "http://en.wikipedia.org/w/api.php?action=query&generator=allpages&gaplimit=2&gapfilterredir=nonredirects&gapfrom=Re&prop=revisions&rvprop=content&format=xml"); 
$xml = curl_exec($ch);
$xml_reader = new XMLReader();
$xml_reader->xml($xml, "UTF-8");

function extract_first_rev(XMLReader $xml_reader)
{
    while ($xml_reader->read()) {
        if ($xml_reader->nodeType == XMLReader::ELEMENT) {
            if ($xml_reader->name == "rev") {
                $content = htmlspecialchars_decode($xml_reader->readInnerXML(), ENT_QUOTES);
                return $content;
            }
        } else if ($xml_reader->nodeType == XMLReader::END_ELEMENT) {
            if ($xml_reader->name == "page") {
                throw new Exception("Unexpectedly found `</page>`");
            }
        }
    }

    throw new Exception("Reached the end of the XML document without finding revision content");
}

$latest_rev = array();
while ($xml_reader->read()) {
    if ($xml_reader->nodeType == XMLReader::ELEMENT) {
        if ($xml_reader->name == "page") {
            $latest_rev[$xml_reader->getAttribute("title")] = extract_first_rev($xml_reader);
        }
    }
}

function parse($rev)
{
    global $ch;

    curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
    curl_setopt($ch, CURLOPT_URL, "http://en.wikipedia.org/w/api.php?action=parse&text=" . rawurlencode($rev) . "&prop=text&format=xml");
    sleep(3);
    $xml = curl_exec($ch);
    $xml_reader = new XMLReader();
    $xml_reader->xml($xml, "UTF-8");

    while ($xml_reader->read()) {
        if ($xml_reader->nodeType == XMLReader::ELEMENT) {
            if ($xml_reader->name == "text") {
                $html = htmlspecialchars_decode($xml_reader->readInnerXML(), ENT_QUOTES);
                return $html;
            }
        }
    }

    throw new Exception("Failed to parse");
}

foreach ($latest_rev as $title => $latest_rev) {
    echo parse($latest_rev) . "\n";
}
person Daniel Trebbien    schedule 29.01.2011
comment
спасибо, @Daniel Trebbien, не возражаете, если я использую curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; he; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8"); вместо $user_agent. - person yuli chika; 30.01.2011
comment
и данные обратно как {{Wiktionary|re|re-}} '''RE''' may mean: * RE ([[:nl:EDP-Auditing|Register EDP auditor]]), Electronic Data Processing auditor, also IT auditor * [[RE (complexity)]], the set of recursively enumerable languages *... это не формат html... - person yuli chika; 30.01.2011
comment
@yuli: Это может сработать, но системным администраторам это не нравится. Вам необходимо указать свой адрес электронной почты. См.: secure.wikimedia.org/wikipedia/meta/wiki/User-Agent_policy< /а> - person Daniel Trebbien; 30.01.2011
comment
@ Даниэль Треббиен, хорошо, я заменил свой адрес электронной почты на веб-браузер. но на этот раз ничего не вернуть. Я вставляю свой код в свою часть сообщения. и возвращаемые данные не в формате html, у вас есть идеи, как их обменять? еще раз спасибо. - person yuli chika; 30.01.2011
comment
@ Даниэль Треббиен, я пытался добавить action=parse, но он возвращает Unrecognized value for parameter 'prop': revisions - person yuli chika; 30.01.2011

Вы можете использовать simplexml:

$xml = simplexml_load_file($url);

См. пример здесь: http://php.net/manual/en/simplexml.examples-basic.php

Или Dom:

$xml = new DomDocument;
$xml->load($url);

Или XmlReader для огромных XML-документов, которые вы не хотите полностью читать в памяти.

person Arnaud Le Blanc    schedule 29.01.2011
comment
При использовании MediaWiki API вы не можете просто вызвать simplexml_load_file для получения XML, потому что ответом будет HTTP 403 Forbidden. Сценарий API блокирует запросы, не содержащие контактную информацию в заголовке User-Agent. - person Daniel Trebbien; 30.01.2011
comment
@user576875, @LadaRaider, Warning: DOMDocument::load(http://en.wikipedia.org/w/api.php?action=query&generator=allpages&gaplimit=2&gapfilterredir=nonredirects&gapfrom=Re&prop=revisions&rvprop=content&format=xml) [domdocument.load]: failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden как добавить $user_agent как @Daniel Trebbien? - person yuli chika; 30.01.2011
comment
@yuli: добавьте ini_set("user_agent", EMAIL_ADDRESS); перед вызовом simplexml_load_file. - person Daniel Trebbien; 30.01.2011

Вам следует взглянуть на класс php XMLReader.

person Dalmas    schedule 29.01.2011