2011-12-21 4 views
0

私はPHPを使ってウェブサイトをスクラップしているので、CSSクラスに基づいてノードを取得する必要があります。 id属性を持たないulタグを取得する必要がありますが、cssクラスはあります。私は、すべてのliタグではなく、特定のアンカータグを含むliタグのみを取得する必要があります。クラス選択と親ノードの取得を可能にするPHP HTMLパーサ

私はDOMDocument、Zend_Domを調べましたが、どちらも要件、クラス選択、DOMトラバーサル(特に親への昇順)のいずれも持っていません。

+3

DOMDocumentでこれを行うことができます.HTMLのサンプルを含める必要があります – ajreal

答えて

2

あなたはを使用することができ、その後、このような何かがうまくいくかもしれない:

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

は、APIのためhttp://api.querypath.org/docs/class_query_path.htmlを参照してください。

(あなたは手間のかかるのDOMDocumentを使用しない場合トラバースは、はるかに簡単です。)

1

。 XPathでクラスごとに選択するのは苦痛ですが、実行することはできます。ここで

は、いくつかのサンプルであるHTML(と完全に有効!):あなたはPHP 5.3を使用している場合は、PHPでのXPath関数を登録することにより、このビットを簡素化することができ

$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); 

。 (ただし、直接ではなくDOMXPathについて、あなたはPHP 5.1から始まるXSLTProcessorでXPath式で使用するための関数を登録することもできます。)

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 
関連する問題