【问题标题】:DOM structure, get element by attribute name/valueDOM结构,通过属性名/值获取元素
【发布时间】:2014-09-02 09:01:09
【问题描述】:

我在 SO 上看到很多与该问题相关的答案,但要么存在我无法克服的细微差异,要么我无法重复显示的过程。

我想要完成的是使用 CURL 从 Google+ 业务页面获取 HTML,迭代 HTML,并为每个业务评论抓取评论 HTML 以显示在非 google+ 网页上的该业务。

每条评论都共享这个父 div 结构:

<div class="ZWa nAa" guidedhelpid="userreviews"> .....

因此,我正在尝试基于为每个具有以下属性的 div 查找和抓取 div 和 innerhtml 来执行 foreach 循环:guidehelpid="userreviews"

我成功地通过 CURL 取回 HTML,并且可以在针对标准 TAG 名称(如“a”)或如果它具有 ID 时对其进行解析,但在查找属性名称时使用 PHP 默认解析器迭代 HTML 是有问题的:

我怎样才能使用下面这个成功的代码,让它像第二个代码中所示的那样工作,这当然是错误的?

工作代码(查找、获取、回显 $output 中的所有“a”标签)

$url = "https://plus.google.com/+Mcgowansac/about";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$output = curl_exec($curl);
curl_close($curl);
$DOM = new DOMDocument;
@$DOM->loadHTML($output);


foreach($DOM->getElementsByTagName('a') as $link) {
        # Show the <a href>
        echo $link->getAttribute('href');
        echo "<br />";}

理论上需要的代码:(通过 HTML 中的自定义属性查找每条评论并回显它们)

$url = "https://plus.google.com/+Mcgowansac/about";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$output = curl_exec($curl);
curl_close($curl);
$DOM = new DOMDocument;
@$DOM->loadHTML($output);


foreach($DOM->getElementsByTagName('div[guidehelpid=userreviews]') as $review) {
        echo $review;
        echo "<br />"; }

我将不胜感激任何帮助我纠正这个问题。如果没有它,我宁愿不使用“simple_html_dom”。

【问题讨论】:

  • 而不是你 getElementsByTagName('div[guidehelpid=userreviews]') 你不能把所有的 div 粘贴在一个大数组中并迭代它们(推出你自己的解决方案?) - 或者你可以使用各种 XQUERY 类型类之一(这就是你的伪代码试图做的对吗?)
  • 好吧,将页面响应中的每个 DIV 粘贴到一个数组中,然后遍历该数组似乎会大大增加脚本负载。也许我错了,但似乎真的效率低下。不过我会尝试一下,看看效果如何。
  • 是的,你是对的,它会增加很多服务器 CPU / 服务器负载 - 我最近没有看过,但如果有一个本地(例如编译的 C)XQUERY 库,那将是理想的它会很好,快速且高效,您可以在那里执行您尝试执行的那种查询
  • 如果不执行页面上的 Javascript,您很可能无法提取所需的所有信息。在这种情况下,我没有确认,但很多 Google 的页面都严重依赖 Javascript 来创建页面上的内容。 PhantomJS 可能是去这里的好方法。如果这不是必需的,您将需要使用 XPath 来定位目标元素 - 如果需要,我可以提供帮助(尽管可能不会持续 ~9 小时)
  • @DaveRandom 谢谢,在获得 Ghost 提供的答案后,我留下的数据格式错误且不一致,因为大多数生成的代码都没有 DIV ID。基本上你的权利,返回的信息很难恢复到可显示的状态,所以我要放弃这种方法。遗憾的是,似乎没有其他人尝试过这个,这将是一个很好的脚本开发,

标签: php dom curl getelementsbytagname


【解决方案1】:

我建议您也可以在这种情况下使用DOMXpath。示例:

$url = "https://plus.google.com/+Mcgowansac/about";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$output = curl_exec($curl);
curl_close($curl);

$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTML($output);
libxml_clear_errors();
$xpath = new DOMXpath($dom);

$review = $xpath->query('//div[@guidedhelpid="userreviews"]');

if($review->length > 0) { // if it exists
    echo $review->item(0)->nodeValue;
    // echoes
    // John DeRemer reviewed 3 months ago Last fall, we had a major issue with mold which required major ... and so on
}

【讨论】:

  • Ghost 看起来很有希望,我已经完成了晚上的工作,但会在早上尝试。感谢您的建议和示例。
  • 再次感谢,我将接受答案,因为它确实返回了结果。但是返回的数据是将其解析为单独的“评论”并使其 CSS 可寻址以进行显示是一项可怕的工作,因为没有 ID 并且 CSS 类不在父级共享。猜猜我只是要放弃这种特殊的方法并尝试一些新的东西。谢谢!
  • @DMSJax 这是 PhantomJS(上面链接)可以真正帮助您的领域。因为它是一个无头浏览器,它允许您从获取的元素中提取计算样式等 - 它不仅限于 DOM 操作,就像 PHP DOM 扩展一样。
  • @DaveRandom 我昨晚简要浏览了一遍,但今天没有返回。一旦我弄清楚了当天的一些项目内容,我会在今天下午更仔细地查看它,看看它是否是一个选项。再次感谢您的建议。
猜你喜欢
  • 2016-02-25
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 2011-11-30
  • 2017-04-03
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
相关资源
最近更新 更多