0

考虑以下格式的文档:

<!DOCTYPE html>
<html>
<head>
<title></title>
<body>
   <div class="blog_post_item first">
       <?php // some child elements ?>
   </div><!-- end blog_post_item -->
</body>
</html>

我正在使用 PHP cURL 将这样的文档从一个域加载到另一个域。我想将我的 cURL 结果修剪为仅包含div.blog_post_item.first及其子项。我知道另一个页面的结构,但我无法编辑它。我想我可以用它preg_match来找到开始和结束标签;它们看起来总是一样的,包括结尾的评论。

我已经搜索了使用 cURL/XPath/XSLT/whatever 进行屏幕抓取的示例/教程,它主要是对 HTML 解析库名称的周期性喋喋不休。因此,请提供一个简单的工作示例。请不要简单地解释使用正则表达式解析 HTML 是一个潜在的安全漏洞。 不要 列出应该进一步阅读规范_ _

我有一些简单的 PHP cURL 代码:

$ch = curl_init("http://a.web.page.com");
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
curl_close($ch);

当然,现在$output包含了整个源码。我将如何获得该元素的内容?

4

3 回答 3

3

如果您确定开始和结束始终相同,那将非常容易。您所要做的就是搜索开头和结尾并匹配它们之间的所有内容。我想很多人会因为我使用正则表达式来查找一些 HTML 而生气,但它会完成这项工作!

// cURL
$ch = curl_init("http://a.web.page.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
curl_close($ch);

if(empty($output)) exit('Couldn\'t download the page');

// finding your data
$pattern = '/<div class="blog_post_item first">(.*?)<\/div><!-- end blog_post_item -->/';

preg_match_all($pattern, $output, $matches);
var_dump($matches); // all matches

因为我不知道您要抓取哪个网站,所以我不确定这是否有效。


在搜索了很长一段时间(确切地说是 26 分钟)后,我找到了为什么它不起作用。点 ( .) 与换行符不匹配。由于 HTML 充满了新行,因此无法匹配内容。无论如何,我使用了一个稍微肮脏的技巧来让它匹配(即使你已经选择了一个答案)。

// cURL
$ch = curl_init('http://blogg.oscarclothilde.com/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
curl_close($ch);

if(empty($output)) exit('Couldn\'t download the page');

// finding your data
$pattern = '/<div class="blog_post_item first">(([^.]|.)*?)<\/div><!-- end blog_post_item -->/';

preg_match_all($pattern, $output, $matches);
var_dump($matches[1][0]); // all matches
于 2012-08-03T09:47:35.427 回答
2

这段代码应该可以工作(>= 5.3.6 和 dom 扩展):

$s = <<<EOM
<!DOCTYPE html>
<html>
<head>
<title></title>
<body>
   <div class="blog_post_item first">
       <?php // some child elements ?>
   </div><!-- end blog_post_item -->
</body>
</html>
EOM;

$d = new DOMDocument;
$d->loadHTML($s);

$x = new DOMXPath($d);

foreach ($x->query('//div[contains(@class, "blog_post_item") and contains(@class, "first")]') as $el) {
        echo $d->saveHTML($el);
}
于 2012-08-03T09:56:13.983 回答
2

如果您确定以下结构:

<div class="blog_post_item first">
   WHATEVER
</div><!-- end blog_post_item -->

并且您确定结束代码不会出现在 WHATEVER 中,那么您可以简单地抓住它。

(请注意,我用 WHATEVER 替换了您原来的 PHP。CURL 只会获取 HTML,它会包含内容,而不是 PHP。)

你不需要正则表达式。您也可以简单地通过搜索想要的字符串来完成,如下面的示例所示。

$curlResponse = '
<!DOCTYPE html>
<html>
<head>
<title></title>
<body>
   <div class="blog_post_item first">
       <?php // some child elements ?>
   </div><!-- end blog_post_item -->
</body>
</html>';

$startStr = '<div class="blog_post_item first">';
$endStr = '</div><!-- end blog_post_item -->';

$startStrPos = strpos($curlResponse, $startStr)+strlen($startStr);
$endStrPos = strpos($curlResponse, $endStr);

$wanted = substr($curlResponse, $startStrPos, $endStrPos-$startStrPos );

echo htmlentities($wanted);
于 2012-08-03T10:07:13.723 回答