【问题标题】:Searching & Extracting Specific text in external webpage via PHP?通过 PHP 在外部网页中搜索和提取特定文本?
【发布时间】:2012-10-25 04:32:40
【问题描述】:

我一直试图从电视剧集跟踪网站中简单地提取“下一集编号”。这是一个示例页面:

Example page

向下滚动,您会看到“倒计时”、“日期”、“季节”和“数字”。我想提取那个数字。

我一直在查看源代码以及 Simple HTML DOM 来尝试解决问题,但我多次失败。 “数字”具有“nextEpInfo”类,但“倒计时”、“季节”...等也具有相同的类。

我将如何提取它?

如果可能的话,我真的很感谢一些很好的参考资料,这些参考资料解释了你推荐的方法,因为理想情况下,当我需要提取的内容被包装在不同的类 div 中时,我想学习如何处理这些情况...等等。

【问题讨论】:

  • 除了匹配属性(即css类),你还需要匹配文本,这里有一个相关的问题:stackoverflow.com/questions/3655549/…
  • @ajreal 感谢您的帖子。但是,由于我试图通过 Simple HTML Dom simplehtmldom.sourceforge.net 提取数字,因此我无法真正将事情联系在一起,因此我很难理解您引用的答案。如果您有时间,是否可以提供示例代码?谢谢!

标签: php dom


【解决方案1】:

如果你有想要解析的页面的原始 HTML,你可以使用 preg_match 来找到它。

如果您没有 HTML,这应该可以帮助您:How do I get the HTML code of a web page in PHP?

preg_match()

此函数可让您使用正则表达式模式解析字符串。建议只解析 HTML 的一小部分,而不是整个页面。例如,在这种情况下,我会尝试获取第一个表格的 HTML(没有上一集信息的那个)。

$subject="the HTML of the url you want to parse";
$pattern='/Number:<\/td><td.+?>(\d+)<\//';
if(preg_match($pattern, $subject, $hits)){
    echo "Number: $hits[0]";
}

如果您不知道正则表达式的工作原理:

'.'是一个保留字符,表示“任何字符”,紧随其后的“+”表示“一个或多个”和“?”使正则表达式不贪婪。所以如果我们总结一下'.+?'意思是“一个或多个任意字符,但要尽可能短”。

'(' 和 ')' 表示我们要检索它们之间的内容,而 '\d' 表示一个数字。所以 '(\d+)' 的意思是'把这个数字组合放在 $hits 数组中'。

如果您使用相同的正则表达式但使用 preg_match_all 您将检索遵循相同模式的所有网络数字,它们将位于 $hits 数组中。

【讨论】:

  • 非常感谢您的提示。经过大约 5 个小时的工作,我设法使用 Simple HTML DOM 完成了它,没有任何复杂性。我使用了 CURL + HTML DOM 的组合。如果他们愿意,我会发布我为其他人所做的事情。不过我有一个重要的问题。我知道如何通过 file_get_contents() 和 curl 检索页面,但我不知道如何检索“部分内容”。感谢任何帮助。
  • 嗯,您可以使用任何 XML 或 DOM 解析器来通过 XPath 获取您想要的部分,或者您可以像以前一样使用正则表达式来获取例如所有的 '/(.+ ?Number:.+?)/',这应该为您提供所有在其任何 td/th 内带有 'Number:' 的表格。
【解决方案2】:

这可以使用 Xpath 完成:

(//td[contains(text(), 'Number')])[1]/../td[2]

此查询导航到文本等于 Number 的第一个 td。然后它转到该孩子的父节点 (/../),然后转到包含下一集编号的第二个 td (td[2])

Firebug 允许您在控制台中使用 $x 测试 Xpath 查询:

$x("(//td[contains(text(), 'Number')])[1]/../td[2]");

要在 PHP 中使用它,请查看 DOMDocumentDOMXpath。更具体的DOMDocument.loadHtmlDOMXpath.query

【讨论】:

    【解决方案3】:

    以下是您可以使用的示例伪代码:

    1) 使用类 nextEpInfo 检索所有 tr:

    foreach($html-&gt;find('tr.nextEpInfo') as $tr)

    2) 对于每个 tr,使用 stristr 验证它们是否包含您的任何关键字。 示例:if(stristr($tr, 'Countdown') !== FALSE)

    3) 如果是这种情况,请提取 tr 下 2 个 tds 的文本内容: $tds = $tr-&gt;find('td')

    4) 从第二个 td 获取所需的值: $tds[1]-&gt;plaintext

    【讨论】:

      【解决方案4】:
      <?php
      /*
      
      <tr class="nextEpInfo">
      <td width="160" align="right" nowrap="" class="nextEpInfo">Season:    </td>
      <td class="nextEpInfo" width="300">4</td>
      </tr>
      */
      $url = 'http://next-episode.net/the-good-wife';
      $ch = curl_init();
      curl_setopt( $ch, CURLOPT_URL, $url );
      curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
      curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
      curl_setopt($ch,CURLOPT_ENCODING, 1);
      curl_setopt( $ch, CURLOPT_REFERER, $url );
      $content = curl_exec ($ch);
      //echo $content;
      $matches = array();
      preg_match_all( '/class="nextEpInfo">(.+):<\/td>\s*<td[^>]*>(\d*)</', $content, $matches );
      print_r( $matches );
      

      或类似的,这是最简单的,只要网站所有者不更改字符串即可。使用 xpath 或其他 xml/html 解析器可能会导致两个字符串匹配的开销,并且如果站点上的内容发生更改,也会以同样的方式制动。

      【讨论】:

        猜你喜欢
        • 2011-08-05
        • 1970-01-01
        • 1970-01-01
        • 2012-06-12
        • 2011-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多