Анализатор PHP HTML, который позволяет мне делать выбор класса и получать родительские узлы - PullRequest
0 голосов
/ 21 декабря 2011

Так что я нахожусь в ситуации, когда я очищаю сайт с помощью PHP, и мне нужно иметь возможность получить узел, основанный на его классе CSS.Мне нужно получить тег ul, который не имеет атрибута id, но имеет класс css.Затем мне нужно получить внутри него только теги li, которые содержат определенные теги привязки, а не все теги li.

Я просматривал DOMDocument, Zend_Dom, и ни у одного из них нет требований, выбора классов и dom.обход (особенно по возрастанию к родителям).

Ответы [ 3 ]

2 голосов
/ 21 декабря 2011

Вы можете использовать , и тогда что-то вроде этого может работать:

htmlqp($html)->find("ul.class")->not("#id")
             ->find('li a[href*="specific"]')->parent()
// then foreach over it or use ->writeHTML() for extraction

См. http://api.querypath.org/docs/class_query_path.html для API.

(Обход гораздо проще, если вы не используете сложный DOMDocument.)

1 голос
/ 21 декабря 2011

Вы можете сделать это с помощью DOMDocument и DOMXPath . Выбор по классам в XPath - это боль, но это можно сделать.

Вот пример (и полностью действительный!) HTML:

$html = <<<EOT
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<title>Document Title</title>
<ul id="myid"><li>myid-listitem1</ul>
<ul class="foo 
theclass
"><li>list2-item1<li>list2-item2</ul>
<ul id="myid2" class="foo&#xD;theclass bar"><li>list3-item1<li>list3-item2</ul>
EOT
;

$doc = new DOMDocument();
$doc->loadHTML($html);
$xp = new DOMXPath($doc);
$nodes = $xp->query("/html/body//ul[not(@id) and contains(concat(' ',normalize-space(@class),' '), ' theclass ')]");

var_dump($nodes->length);

Если вы используете PHP 5.3, вы можете немного упростить это, зарегистрировав функцию XPath в php. (Обратите внимание, что вы можете зарегистрировать функции для использования в выражениях XPath по XSLTProcessor, начиная с PHP 5.1, но не напрямую по DOMXPath.)

function hasToken($nodearray, $token) {
    foreach ($nodearray as $node) {
        if ($node->nodeValue===null or !hasTokenS($node->nodeValue, $token)) {
            return False;
        }
    }
    return True;
    // I could even return nodes or document fragments if I wanted!
}
function hasTokenS($str, $token) {
    $str = trim($str, "\r\n\t ");
    $tokens = preg_split('/[\r\n\t ]+/', $str);
    return in_array($token, $tokens);
}

$xp->registerNamespace('php', 'http://php.net/xpath');
$xp->registerPhpFunctions(array('hasToken', 'hasTokenS'));

// These two are equivalent:
$nodes1 = $xp->query("/html/body//ul[not(@id) and php:function('hasToken', @class, 'theclass')]");
$nodes2 = $xp->query("/html/body//ul[not(@id) and php:functionString('hasTokenS', @class, 'theclass')]");

var_dump($nodes1->length);
var_dump($nodes1->item(0));
var_dump($nodes2->length);
var_dump($nodes2->item(0));

Если DOMDocument просто не очень хорошо разбирает ваш HTML, вы можете использовать синтаксический анализатор html5lib , который будет возвращать DOMDocument:

require_once('lib/HTML5/Parser.php'); // or where-ever you put it
$dom = HTML5_Parser::parse($html);
// $dom is a plain DOMDocument object, created according to html5 parsing rules
0 голосов
/ 21 декабря 2011

мне повезло с: http://simplehtmldom.sourceforge.net/

...