php 通过类名获取DOM元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6366351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:09:02  来源:igfitidea点击:

Getting DOM elements by classname

phpcssdom

提问by bgcode

I'm using PHP DOMand I'm trying to get an element within a DOM node that have a given class name. What's the best way to get that sub-element?

我正在使用PHP DOM并且我试图在具有给定类名的 DOM 节点中获取一个元素。获取该子元素的最佳方法是什么?

Update:I ended up using Mechanizefor PHP which was much easier to work with.

更新:我最终使用Mechanize了 PHP,它更容易使用。

回答by prodigitalson

Update: Xpath version of *[@class~='my-class']css selector

更新:*[@class~='my-class']CSS 选择器的Xpath 版本

So after my comment below in response to hakre's comment, I got curious and looked into the code behind Zend_Dom_Query. It looks like the above selector is compiled to the following xpath (untested):

因此,在我对 hakre 的评论做出以下评论之后,我很好奇并查看了Zend_Dom_Query. 看起来上面的选择器被编译为以下 xpath(未经测试):

[contains(concat(' ', normalize-space(@class), ' '), ' my-class ')]

[contains(concat(' ', normalize-space(@class), ' '), ' my-class ')]

so the php would be:

所以php将是:

$dom = new DomDocument();
$dom->load($filePath);
$finder = new DomXPath($dom);
$classname="my-class";
$nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]");

Basically, all we do here is normalize the classattribute so that even a single class is bounded by spaces, and the complete class list is bounded in spaces. Then append the class we are searching for with a space. This way we are effectively looking for and find only instances of my-class.

基本上,我们在这里所做的只是对class属性进行规范化,这样即使是单个类也以空格为界,而完整的类列表也以空格为界。然后用空格附加我们正在搜索的类。这样我们就可以有效地寻找并只找到my-class.



Use an xpath selector?

使用 xpath 选择器?

$dom = new DomDocument();
$dom->load($filePath);
$finder = new DomXPath($dom);
$classname="my-class";
$nodes = $finder->query("//*[contains(@class, '$classname')]");

If it is only ever one type of element you can replace the *with the particular tagname.

如果它只是一种类型的元素,您可以用*特定的标记名替换。

If you need to do alot of this with very complex selector i would recommend Zend_Dom_Querywhich supports CSS selector syntax (a la jQuery):

如果你需要用非常复杂的选择器做很多这样的事情,我会推荐Zend_Dom_Query它支持 CSS 选择器语法(a la jQuery):

$finder = new Zend_Dom_Query($html);
$classname = 'my-class';
$nodes = $finder->query("*[class~=\"$classname\"]");

回答by Tschallacka

If you wish to get the innerhtml of the class without the zend you could use this:

如果你想在没有 zend 的情况下获得类的innerhtml,你可以使用这个:

$dom = new DomDocument();
$dom->load($filePath);
$classname = 'main-article';
$finder = new DomXPath($dom);
$nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]");
$tmp_dom = new DOMDocument(); 
foreach ($nodes as $node) 
    {
    $tmp_dom->appendChild($tmp_dom->importNode($node,true));
    }
$innerHTML.=trim($tmp_dom->saveHTML()); 
echo $innerHTML;

回答by dav

I think the accepted way is better, but I guess this might work as well

我认为公认的方式更好,但我想这也可能有效

function getElementByClass(&$parentNode, $tagName, $className, $offset = 0) {
    $response = false;

    $childNodeList = $parentNode->getElementsByTagName($tagName);
    $tagCount = 0;
    for ($i = 0; $i < $childNodeList->length; $i++) {
        $temp = $childNodeList->item($i);
        if (stripos($temp->getAttribute('class'), $className) !== false) {
            if ($tagCount == $offset) {
                $response = $temp;
                break;
            }

            $tagCount++;
        }

    }

    return $response;
}

回答by oabarca

There is also another approach without the use of DomXPathor Zend_Dom_Query.

还有另一种不使用DomXPathor 的方法Zend_Dom_Query

Based on dav's original function, I wrote the following function that returns all the children of the parent node whose tag and class match the parameters.

基于 dav 的原始函数,我编写了以下函数,该函数返回标签和类与参数匹配的父节点的所有子节点。

function getElementsByClass(&$parentNode, $tagName, $className) {
    $nodes=array();

    $childNodeList = $parentNode->getElementsByTagName($tagName);
    for ($i = 0; $i < $childNodeList->length; $i++) {
        $temp = $childNodeList->item($i);
        if (stripos($temp->getAttribute('class'), $className) !== false) {
            $nodes[]=$temp;
        }
    }

    return $nodes;
}

suppose you have a variable $htmlthe following HTML:

假设您有一个$html以下 HTML的变量:

<html>
 <body>
  <div id="content_node">
    <p class="a">I am in the content node.</p>
    <p class="a">I am in the content node.</p>
    <p class="a">I am in the content node.</p>    
  </div>
  <div id="footer_node">
    <p class="a">I am in the footer node.</p>
  </div>
 </body>
</html>

use of getElementsByClassis as simple as:

使用getElementsByClass很简单:

$dom = new DOMDocument('1.0', 'utf-8');
$dom->loadHTML($html);
$content_node=$dom->getElementById("content_node");

$div_a_class_nodes=getElementsByClass($content_node, 'div', 'a');//will contain the three nodes under "content_node".

回答by iautomation

DOMDocumentis slow to type and phpQueryhas bad memory leak issues. I ended up using:

DOMDocument打字很慢,而且phpQuery有严重的内存泄漏问题。我最终使用了:

https://github.com/wasinger/htmlpagedom

https://github.com/wasinger/htmlpagedom

To select a class:

要选择一个班级:

include 'includes/simple_html_dom.php';

$doc = str_get_html($html);
$href = $doc->find('.lastPage')[0]->href;

I hope this helps someone else as well

我希望这对其他人也有帮助