更好的方式来获得一个页面的html源


Better way to get the html source of a page

我试图通过过滤其源代码在网页上获得一些数据,我发现了很多方法来抓取网页的html内容,如$html = file_get_html('http://www.exam.com/results/');curlhtml获取源

获取一个页面的html源代码的最好方法是什么?还是所有这些方法都是一样的?

cURL可能比file_get_contents($url) *****提供更好的性能。我更愿意使用cURL,因为所有这些函数最终都会检索到特定的网页内容,唯一的区别是运行时间,正如我所说的,使用cURL时运行时间更好。

*你可以在这里找到一个像样的(但不是正式的)证明,包括一个基准:https://stackoverflow.com/questions/555523/file-get-contents-vs-curl-what-has-better-performance

这取决于您需要什么,但重要的是要记住,curl将作为文本返回响应,而file_get_html将返回Simple_HTML_DOM。此外,我认为重要的是要注意file_get_html在引擎盖下调用file_get_contents

就我个人而言,我有一个温和的偏好,首先将数据加载到内存中(我发现它更容易调试),但我通常不喜欢使用curl_*,除非我需要发送一些头与请求(POST变量或WWW-Auth头,等)。我发现它把一行函数调用变成了一团乱码。所以我通常依靠file_get_contents

至于Simple_HTML_DOM,我想知道它是否可能比PHP本地编译库更快。您可以使用simplexml_load_fileDomDocument::loadHTMLFile访问它们。

对于很多用途,一个file_get_contents()就足够了。但是在很多情况下,你需要特殊的要求。

使用PHP流上下文:如果没有curl可用,并且您必须在请求中放置POST-Data

Curl:获取http内容的瑞士军刀,通常效果最好。如果可能的话,有一种特殊情况您应该使用curl:如果您获取远程页面,您自己的请求被阻塞。在这种情况下,您依赖于远程站点的性能。如果您使用的是像Apache2这样具有有限插槽的web服务器,那么如果远程站点太慢或无法访问,它们可能会被填满。我遇到过一些类似的服务器宕机情况。Curl通过为请求设置超时来帮助您。最好把它设置得低一点,比如3秒。

但是最好的方法是使用cronjob或类似的方法获取外部内容,缓存它并使用缓存的版本。

cURL提供了更多的控制,正如@itamar所建议的那样。它允许您设置一些使用file_get_contents无法设置的内容,包括:

    代理使用
  • <
  • 头/gh>
  • 永久cookie存储

它还允许您检索标题。

cURL的使用是相当复杂的,但是回报是相当不错的。建议将其封装在函数中。我倾向于这样写:

protected static function prepare_channel(Request $r) {
    $r->channel = curl_init();
    $p = array();
    foreach ($r->GET as $k => $v) {
        $p[] = $k."=".$v;
    }
    $head = array();
    foreach ($r->getHeaders() as $k => $v) {
        $head[] = $k.": ".$v;
    }
    curl_setopt($r->channel, CURLOPT_URL, $r->getURI()."?".implode("&",$p));
    curl_setopt($r->channel, CURLOPT_HTTPHEADER, $head);
    curl_setopt($r->channel, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($r->channel, CURLOPT_FORBID_REUSE, true);
    curl_setopt($r->channel, CURLOPT_RETURNTRANSFER, true);
    if (Request::getProxy()) {
        curl_setopt($r->channel, CURLOPT_PROXY, Request::getProxy());
    }
    curl_setopt($r->channel, CURLOPT_HEADER, true);
    return $r->channel;
}

这是一个活动代码,我的Request对象具有以下签名:

protected $headers = array();
protected $baseURI = "";
public $GET = array();
public $POST = array();

运行$result = curl_exec($r->channel);返回报头和正文。然后你可以这样分割它们:

 $header_size = curl_getinfo($r->channel, CURLINFO_HEADER_SIZE);
 $headers = substr($result, 0, $header_size);
 $body = substr($result, $header_size);

从那里,你可以自由地做任何你喜欢的$header$body。您还可以通过运行curl_getinfo($r->channel)获得大量信息。

要在PHP中解析HTML,最好先做两件事:

  • tidy松开它以清除格式错误的标记
  • 使用DOMDocument解析