天道酬勤,学无止境

使用 DOMDocument,是否可以获取某个 DOM 中存在的所有元素?(Using DOMDocument, is it possible to get all elements that exists within a certain DOM?)

问题

假设我有一个包含许多不同元素的 HTML 文件,每个元素都有不同的属性。 假设我事先不知道这个 HTML 会是什么样子。

使用 PHP 的 DOMDocument,如何遍历所有元素并修改它们? 我所看到的只是 getElementByTagName 和 getElementById 等。我想遍历所有元素。

例如。 假设 HTML 看起来像这样(只是一个例子,实际上我不知道结构):

$html = '<div class="potato"><span></span></div>';

我希望能够进行一些简单的 DOM 修改(如在 Javascript 中):

$dom = new DOMDocument();
$dom->loadHTML($html);

// Obviously the code below doesn't work but showcases what I want to achieve
foreach($dom->getAllElements as $element ){
    if(!$element->hasClass('potato')){
       $element->addClass('potato');
    } else{
       $element->removeClass('potato');
    }
}
$html = $dom->SaveHTML();

因此,在这种情况下,我希望生成的 html 如下所示:

    $html = '<div><span class="potato"></span></div>';

那么如何遍历所有元素并在 foreach 循环中即时进行修改? 我真的不想为此使用正则表达式。

回答1

您可以使用返回所有元素的 getElementsByTagName() 传递星号*

foreach($dom->getElementsByTagName('*') as $element ){

}

从手册:

名称
要匹配的标记的本地名称(没有命名空间)。 特殊值 * 匹配所有标签。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 抓取A元素的href属性(Grabbing the href attribute of an A element)
    问题 试图在页面上找到链接。 我的正则表达式是: /<a\s[^>]*href=(\"\'??)([^\"\' >]*?)[^>]*>(.*)<\/a>/ 但似乎失败了 <a title="this" href="that">what?</a> 我该如何更改我的正则表达式以处理未置于a标签首位的href? 回答1 可靠的HTML正则表达式很困难。 这是使用DOM的方法: $dom = new DOMDocument; $dom->loadHTML($html); foreach ($dom->getElementsByTagName('a') as $node) { echo $dom->saveHtml($node), PHP_EOL; } 上面的代码将找到并输出$html字符串中所有A元素的“ outerHTML”。 要获取节点的所有文本值,请执行以下操作 echo $node->nodeValue; 要检查href属性是否存在,您可以执行以下操作 echo $node->hasAttribute( 'href' ); 要获取href属性,您需要执行 echo $node->getAttribute( 'href' ); 更改href属性 $node->setAttribute('href', 'something else'); 删除href属性 $node-
  • 如何使用DOMDocument类删除HTML元素(How to remove an HTML element using the DOMDocument class)
    问题 有没有一种使用DOMDocument类删除HTML元素的方法? 回答1 http://us2.php.net/manual/zh/domnode.removechild.php DomDocument是一个DomNode。您可以仅调用remove child,就可以了。 编辑:刚注意到您可能正在谈论您当前正在使用的页面。 不知道DomDocument是否会工作。 您可能想在那时使用javascript(如果已将其提供给客户端) 回答2 除了Dave Morgan的答案,您还可以使用DOMNode::removeChild从子级列表中删除子级: 通过标签名称删除一个孩子 //The following example will delete the table element of an HTML content. $dom = new DOMDocument(); //avoid the whitespace after removing the node $dom->preserveWhiteSpace = false; //parse html dom elements $dom->loadHTML($html_contents); //get the table from dom if($table = $dom->getElementsByTagName('table
  • PHP中的DOMDocument(DOMDocument in php)
    问题 我刚刚开始阅读有关DOM的文档和示例,以便对文档进行爬网和解析。 例如,我有一部分文档如下所示: <div id="showContent"> <table> <tr> <td> Crap </td> </tr> <tr> <td width="172" valign="top"><a href="link"><img height="91" border="0" width="172" class="" src="img"></a></td> <td width="10"> </td> <td valign="top"><table cellspacing="0" cellpadding="0" border="0"> <tbody><tr> <td height="30"><a class="px11" href="link">title</a><a><br> <span class="px10"></span> </a></td> </tr> <tr> <td><img height="1" width="580" src="crap"></td> </tr> <tr> <td align="right"> <a href="link"><img height="16" border="0" width="65" src="/buy"></a> </td> </tr>
  • 删除父元素,并使用saveHTML将所有内部子元素保留在DOMDocument中(Remove parent element, keep all inner children in DOMDocument with saveHTML)
    问题 我正在用XPath处理一个简短的HTML代码段; 当我使用$ doc-> saveHTML()将更改后的代码片段输出回来时,将添加DOCTYPE ,并且HTML / BODY标记会包装输出。 我想删除这些子项,但仅通过使用DOMDocument函数将所有子项保留在其中。 例如: $doc = new DOMDocument(); $doc->loadHTML('<p><strong>Title...</strong></p> <a href="http://www....."><img src="http://" alt=""></a> <p>...to be one of those crowning achievements...</p>'); // manipulation goes here echo htmlentities( $doc->saveHTML() ); 这将产生: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ...> <html><body> <p><strong>Title...</strong></p> <a href="http://www....."><img src="http://" alt=""></a> <p>...to be one of those
  • 如何在$ _SESSION中序列化/保存DOMElement?(How to serialize/save a DOMElement in $_SESSION?)
    问题 我对PHP,DOM和PHP DOM实现非常陌生。 我正在尝试将DOMDocument的根元素保存在$_SESSION变量中,以便我可以访问它并在后续页面加载时对其进行修改。 但是在使用$_SESSION保存DOMElement的状态时,PHP出现错误: 警告:DOMNode :: appendChild()[domnode.appendchild]:无法获取DOMElement 我读过一个PHP DOMDocument对象不能本地保存到$_SESSION 。 但是,可以通过保存DOMDocument的序列化来保存它(例如$_SESSION['dom'] = $dom->saveXML() )。 我不知道将DOMElement保存到$_SESSION变量中是否同样适用,但这就是我正在尝试的方法。 我想要这样做的原因是使用带有一个附加属性的DOMElement扩展类。 我希望通过将根DOMElement保存在$ _SESSION中,以后可以检索该元素并修改此附加属性,然后执行测试,例如(if(additionalProperty === false){ }。 我还阅读了通过保存DOMDocument并在以后检索它的方式,所有元素都作为本机DOM类中的对象返回。 就是说,即使我使用扩展类来创建元素,我随后需要的属性也将无法访问,因为持有对扩展类对象的引用的变量已超出范围
  • PHP5:在DOMDocument中查找根节点(PHP5: Find Root Node in DOMDocument)
    问题 我有一个PHP5 DOMDocument,我尝试查找根节点(而不是根元素)。 例子: <test> <element> <bla1>x</bla1> <bla2>x</bla2> </element> <element> <bla1>y</bla1> <bla2>y</bla2> </element> <element> <bla1>z</bla1> <bla2>z</bla2> </element> </test> 我想获取“测试”的DOMNode,以便可以调用-例如-hasChildNodes。 我可以获取“ documentElement”,但这是一个DOMElement。 也许我可以从那里去吗? $d = DOMDocument::loadXML($xml); // [... do some stuff here to find document's root node ...] if ($rootnode->hasChildNodes()) echo 'yayy!' 谁可以填补空白? 我似乎是瞎子。 (显然,这不仅是我要调用的hasChildNodes-因此,不,它也无助于寻找另一种方法来确定文档中是否包含东西。这仅是我的简单示例。我最后需要一个DOMNode。) 回答1 根据PHP文档,DOMElement是DOMNode的子类
  • 如何使用PHP将HTML转换为JSON?(How to convert HTML to JSON using PHP?)
    问题 我可以使用JsontoHtml库将JSON转换为HTML。 现在,我需要将当前的HTML转换为JSON,如本网站所示。 当查看代码时,我发现以下脚本: <script> $(function(){ //HTML to JSON $('#btn-render-json').click(function() { //Set html output $('#html-output').html( $('#html-input').val() ); //Process to JSON and format it for consumption $('#html-json').html( FormatJSON(toTransform($('#html-output').children())) ); }); }); //Convert obj or array to transform function toTransform(obj) { var json; if( obj.length > 1 ) { json = []; for(var i = 0; i < obj.length; i++) json[json.length++] = ObjToTransform(obj[i]); } else json = ObjToTransform(obj); return(json);
  • PHP DomDocument无法处理utf-8字符(☆)(PHP DomDocument failing to handle utf-8 characters (☆))
    问题 网络服务器使用utf-8编码提供响应,所有文件都使用utf-8编码保存,我所知道的所有设置都已设置为utf-8编码。 这是一个快速程序,用于测试输出是否有效: <?php $html = <<<HTML <!doctype html> <html> <head> <meta charset="utf-8"> <title>Test!</title> </head> <body> <h1>☆ Hello ☆ World ☆</h1> </body> </html> HTML; $dom = new DomDocument("1.0", "utf-8"); $dom->loadHTML($html); header("Content-Type: text/html; charset=utf-8"); echo($dom->saveHTML()); 该程序的输出为: <!DOCTYPE html> <html><head><meta charset="utf-8"><title>Test!</title></head><body> <h1>â&#152;&#134; Hello â&#152;&#134; World â&#152;&#134;</h1> </body></html> 呈现为: 你好-世界- 我可能做错了什么? 我必须告诉DomDocument正确处理utf
  • PHP DOM:如何以一种优雅的方式通过标记名称获取子元素?(PHP DOM: How to get child elements by tag name in an elegant manner?)
    问题 我正在解析一些具有PHP DOM扩展名的XML,以便以其他形式存储数据。 毫不奇怪,当我解析一个元素时,我经常需要获取某个名称的所有子元素。 有方法DOMElement::getElementsByTagName($name) ,但它返回具有该名称的所有后代,而不仅仅是直接子代。 还有DOMNode::$childNodes但是(1)它包含节点列表,而不是元素列表,即使我设法将列表项变成元素(2),我仍然需要检查所有这些元素以获取名称。 真的没有一种优雅的解决方案来仅获得某个特定名称的子级,还是我在文档中缺少某些内容? 一些插图: <?php DOMDocument(); $document->loadXML(<<<EndOfXML <a> <b>1</b> <b>2</b> <c> <b>3</b> <b>4</b> </c> </a> EndOfXML ); $bs = $document ->getElementsByTagName('a') ->item(0) ->getElementsByTagName('b'); foreach($bs as $b){ echo $b->nodeValue . "\n"; } // Returns: // 1 // 2 // 3 // 4 // I'd like to obtain only: // 1 // 2 ?> 回答1
  • 如何使用SimpleXML解析XML的CDATA HTML内容?(How to parse CDATA HTML-content of XML using SimpleXML?)
    问题 我正在尝试在表格中显示Xml内容,所有内容都可以正常运行,但是标签中的某些内容我不想显示,我只希望图像而不想要 2012年11月日历(来自5.10测试) like in xml, <content:encoded><![CDATA[<p>November 2012 calendar from 5.10 The Test</p> <p><a class="shutterset_" href='http://trance-gemini.com/wordpress/wp-content/gallery/calendars/laura-bertram-trance-gemini-145-1080.jpg' title='<br>November 2012 calendar from 5.10 The Test<br> <a href="</a></p>]]> </content:encoded> 我想显示图像但不显示 2012年11月日历(来自5.10测试) . <?php // load SimpleXML $item = new SimpleXMLElement('test1.xml', null, true); echo <<<EOF <table border="1px"> <tr cl> </tr> EOF; foreach($item->channel->item as
  • 没有HTML包装器的情况下如何保存DOMDocument的HTML?(How to saveHTML of DOMDocument without HTML wrapper?)
    问题 我是下面的函数,我正在努力输出DOMDocument,而没有在内容输出之前附加XML,HTML, body和p标签包装器。 建议的修复方法: $postarray['post_content'] = $d->saveXML($d->getElementsByTagName('p')->item(0)); 仅当内容中没有块级元素时才起作用。 但是,这样做时(如下面的示例中带有h1元素的示例),saveXML的结果输出将被截断为... <p>如果你喜欢</ p> 我已经指出此帖子是一种可能的解决方法,但我不明白如何将其实现到此解决方案中(请参阅下面的注释尝试)。 有什么建议? function rseo_decorate_keyword($postarray) { global $post; $keyword = "Jasmine Tea" $content = "If you like <h1>jasmine tea</h1> you will really like it with Jasmine Tea flavors. This is the last ocurrence of the phrase jasmine tea within the content. If there are other instances of the keyword jasmine tea
  • 如何在片段创建中使用全局名称空间定义?(How to use global namespace definitions in a fragment creation?)
    问题 根元素具有名称空间声明,例如xmlns:xlink="http://www.w3.org/1999/xlink" ...,因此,任何附加节点(例如appendChild )都将接受该名称空间。 我可以附加<graphic xlink:href=".."/>因为总体上是有效的...但是要附加一个片段,我首先需要使用createDocumentFragment()创建该片段。 例子: $tmp = $dom->createDocumentFragment(); $ok = $tmp->appendXML('<graphic xlink:href="file123.ext"/>'); 运行时,生成错误, DOMDocumentFragment::appendXML(): namespace error : Namespace prefix xlink for href on inline-graphic is not defined 如何对DOMDocumentFragment::appendXML()方法说“使用DomDocument命名空间”? 注释和上下文 (作为答案转移,不要在这里污染) 回答1 看起来它正在按预期的方式运行。 查看错误报告#44773。 chregu@php.net表示这不是错误,并且可以正常工作。 尽管我会同意该错误报告和其他评论
  • Selenium之操作浏览器、元素等待、窗体切换和弹窗处理
    浏览器操作控制浏览器窗口大小浏览器设置最大化driver.maximize_window()设置浏览器显示大小driver.set_window_size(1480, 800)控制浏览器前进后退后退:driver.back()前进:driver.forward()效果演示: 模拟浏览器刷新driver.refresh()简单的元素操作最常用的几个方法:clear() 清除文本send_keys(*values) 模拟按键输入click() 单击元素submit() 用于提交表单,有时候可以与click()方法互换使用获取元素的某些属性:size: 返回元素的尺寸text: 返回元素的文本get_attribute(name): 获得属性值is_displayed(): 获取该元素是否用户可见is_enabled(): 判断元素是否可用is_selected(): 判断元素是否被选中 模拟鼠标操作由于现在web端页面提供了更丰富的鼠标交互方式,因此,在做UI自动化的过程中可能会用到鼠标的右击、双击、悬停、甚至是鼠标拖动等功能。这些在WebDriver 中都是支持的,基于鼠标的相关操作方法都封装在ActionChains类中。以python为例,需要先导入对应的包:from selenium.webdriver.common.action_chains import
  • 您如何在PHP中解析和处理HTML / XML?(How do you parse and process HTML/XML in PHP?)
    问题 如何解析HTML / XML并从中提取信息? 回答1 本机XML扩展 我更喜欢使用本机XML扩展之一,因为它们与PHP捆绑在一起,通常比所有第3方库都快,并为我提供了所需的标记控制权。 判断 DOM扩展使您可以使用PHP 5通过DOM API通过XML文档进行操作。它是W3C的Document Object Model Core Level 3的实现,它是一种平台和语言无关的界面,允许程序和脚本动态访问和更新。文件的内容,结构和样式。 DOM能够解析和修改真实世界(损坏的)HTML,并且可以执行XPath查询。 它基于libxml。 使用DOM需要花一些时间,但是IMO值得花时间。 由于DOM是与语言无关的接口,因此您会发现许多语言的实现,因此,如果您需要更改编程语言,那么您很可能已经知道如何使用该语言的DOM API。 一个基本的用法示例可以在Gradinging A element的href属性中找到,而一般的概念性概述可以在php中的DOMDocument中找到。 StackOverflow上已广泛讨论了如何使用DOM扩展,因此,如果您选择使用它,则可以确保可以通过搜索/浏览Stack Overflow来解决所遇到的大多数问题。 XMLReader XMLReader扩展是XML提取解析器。 阅读器充当光标,在文档流上前进,并在途中的每个节点处停止。 像DOM一样
  • 使用 DOMDocument::loadHTML 和 getElementsByTagName 通过标签名称获取 DOM 元素(Get DOM elements by tag name with DOMDocument::loadHTML and getElementsByTagName)
    问题 对不起,如果这是重新发布的,但我无法解决它,我已经尝试了所有可用的文档和我能找到的示例。 我正在尝试获取包含 HTML 的字符串的第一个img元素 PHP $html = '<p><img src="http://placekitten.com/200/300" alt="" width="200" height="300" /></p>'; $dom = new DOMDocument; $dom->loadHTML($html); $imgs = $dom->getElementsByTagName('img'); var_dump($imgs); 当它应该找到一个出现时,这会吐出object(DOMNodeList)#57 (0) { } 。 我试过 XPath 也没有运气。 回答1 用这个: $img = $dom->getElementsByTagName('img')->item(0); echo $img->attributes->getNamedItem("src")->value; 回答2 正确的答案已经被@nickb提供的,但你也可以做同样的,而不必使用getNamedItem()由@nickb提供,这样的代码的第二行: echo $img->attributes->src->value; 注意:我想将上述代码添加为@nickb答案的注释,但我至少需要
  • 使用DomDocument将所有标头标签替换为h4标签(Use DomDocument to replace all header tags with the h4 tags)
    问题 我已经使用DomDocument到GetElementById。 它选择了一个div。 我需要用h4标签替换该div中的所有标头标签。 回答1 您尚未清楚问题所遇到的具体问题。 我认为其中有两个部分可能会引起一些问号。 第一个是如何使用要重命名的所有元素的方法,第二个实际上是如何重命名元素的方法。 获取DOMDocument的标题元素 因此首先要做的是:要选择所有标头元素,您需要选择所有作为标头元素(h1至h6)的标签。 再加上他们还必须是具有特定id属性的div标记的子代的条件,这似乎是一件相当复杂的事情。 但是,对于xpath查询,它仍然只是简单明了。 对于我的代码示例,我选择了id`“ content”,下面的xpath表达式查询所有标题元素: ( //div[@id="content"]//h1 |//div[@id="content"]//h2 |//div[@id="content"]//h3 |//div[@id="content"]//h4 |//div[@id="content"]//h5 |//div[@id="content"]//h6 ) 如果我在此网站上(在回答之前)运行此文件,它将创建以下标签列表: Found 8 elements: #00: <h1> #01: <h2> #02: <h2> #03: <h3> #04: <h3> #05:
  • 通过类名获取DOM元素(Getting DOM elements by classname)
    问题 我正在使用PHP DOM,并且试图在DOM节点中获取具有给定类名的元素。 获得该子元素的最佳方法是什么? 更新:我最终使用了Mechanize for PHP,它更容易使用。 回答1 更新: *[@class~='my-class'] class〜 *[@class~='my-class'] css选择器的Xpath版本 因此,在下面针对hakre的评论做出评论之后,我感到好奇,并查看了Zend_Dom_Query背后的代码。 看起来上述选择器已编译为以下xpath(未经测试): [contains(concat(' ', normalize-space(@class), ' '), ' my-class ')] 因此,PHP将是: $dom = new DomDocument(); $dom->load($filePath); $finder = new DomXPath($dom); $classname="my-class"; $nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]"); 基本上,我们在这里所做的就是规范化class属性,以便即使单个类也受空格限制,而完整的类列表也受空格限制。 然后在要搜索的类后面加上一个空格。
  • 使用DOMdocument()方法按ClassName获取元素(Get Element by ClassName with DOMdocument() Method)
    问题 这是我想要达到的目的:检索页面上的所有产品并将它们放入数组中。 这是我正在使用的代码: $page2 = curl_exec($ch); $doc = new DOMDocument(); @$doc->loadHTML($page2); $nodes = $doc->getElementsByTagName('title'); $noders = $doc->getElementsByClassName('productImage'); $title = $nodes->item(0)->nodeValue; $product = $noders->item(0)->imageObject.src; 它适用于$title but不适用于产品。 有关信息,在HTML代码中,img标签如下所示: <img alt="" class="productImage" data-altimages="" src="xxxx"> 我一直在看这个(PHP DOMDocument如何获取元素?),但我仍然不明白如何使其工作。 PS:我收到此错误: 调用未定义的方法DOMDocument::getElementsByclassName() 回答1 我终于使用了以下解决方案: $classname="blockProduct"; $finder = new DomXPath($doc);
  • 如何使HTML5与DOMDocument一起使用?(How to make HTML5 work with DOMDocument?)
    问题 我正在尝试使用DOMDocument解析HTML代码,对它进行更改之类的操作,然后将其组合回发送给输出的字符串。 但是存在一些与解析有关的问题,这意味着我发送给DOMDocument的内容并不总是以相同的形式返回:) 以下是清单: 使用-> loadHTML: 设置文件格式时,无论preserveWhitespace和formatOutput设置如何(在预格式化的文本上丢失空白) 当我具有html5标签(例如<header> , <footer>等)时,会给我错误。但是可以禁止使用,所以我可以忍受这个错误。 产生不一致的标记-例如,如果我添加<link ... />元素(带有自动关闭标签),则在解析/ saveHTML之后,输出将为<link .. > 使用-> loadXML: 从<style>或<script>标签对诸如>实体进行编码: body > div成为body > div body > div 所有标签都以相同的方式关闭,例如<meta ... />变为<meta...></meta> ; 但这可以用正则表达式解决。 我没有尝试HTML5lib,但是出于性能方面的考虑,我更喜欢使用DOMDocument而不是自定义解析器 更新: 因此,就像提到的使用CDATA的Honeymonster一样,可以解决loadXML的主要问题。
  • Python爬虫学习笔记 (13) [中级] 动态网页处理 selenium
    更新日期: 2021.04.05 本节学习内容 : 处理动态网页的利器 selenium~ 目录 1. selenium是什么?2. 安装时可能遇到的问题3. 定位webdriver对象4. 操控webdriver对象4.1 获取对象相关信息4.2 提交信息 & 点击4.3 拖放鼠标4.4 滚动页面4.5 前进/后退一页 & 关闭标签/浏览器 5. 监听webdriver操控结果(条件等待)6. 小练习7. selenium的其他方法 - 暂时 不学8. 总结~ 1. selenium是什么? selenium是一套web测试系统,包含了测试的录制,编写和运行,以及测试的并行处理。支持多种主流浏览器。 官网文档:selenium package APISelenium with Python中文翻译文档 selenium被应用在爬虫中,是因为它可以模拟人的操作来驱动浏览器,完成加载动态网页所要求的点击和下拉等动作,以获取网页的完整代码。selenium驱动浏览器操作的过程是可以在网页上直接观察到的,也可以使用无界面模式。 通过selenium获取内容需等待页面加载完毕,所以速度比直接构造请求获取内容慢,因此应仅在requests不能胜任时使用。 使用selenium 的基本流程: 设置 action chains:驱使浏览器按顺序执行预定操作(如找到"下拉获取更多信息"的按键并点击