比file_get_contents()更快的替代方法

13

目前我使用file_get_contents()将GET数据提交到一组站点的数组中,但在执行页面时,我收到以下错误:

致命错误:超过30秒的最大执行时间

我真正想让脚本做的只是开始加载网页,然后离开。每个网页可能需要长达5分钟才能完全加载,而我不需要它完全加载。

这是我当前的代码:

        foreach($sites as $s) //Create one line to read from a wide array
        {
                file_get_contents($s['url']); // Send to the shells
        }

编辑:为了消除任何困惑,此脚本用于启动其他服务器上的脚本,不返回任何数据。

编辑:我现在尝试使用cURL来完成这个技巧,通过设置一秒钟的超时时间来发送数据然后停止。以下是我的代码:

        $ch = curl_init($s['url']); //load the urls
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1); //Only send the data, don't wait.
        curl_exec($ch); //Execute
        curl_close($ch); //Close it off.

也许我设置选项时出错了。我正在查看一些手册。只是给你们一个更新。感谢所有帮助我的人。

编辑:啊,找到问题了。我使用的是CURLOPT_CONNECTTIMEOUT而不是CURLOPT_TIMEOUT。糟糕。

但现在,脚本没有触发。它们每个都使用ignore_user_abort(TRUE);所以我无法理解问题所在。

哈哈,撤销刚才的话。现在可以工作了。非常感谢大家。


不,我没有使用cURL的经验。想用一些我至少有一点经验的东西来完成它。你认为我应该放弃php,改用cURL吗? - Rob
这个网页到底是做什么的?你只是想让它启动一个自行运行且不返回任何数据的脚本吗? - Tor Valamo
@Rob 它仍然需要运行,对吗?这意味着它需要等待远程站点完成数据发送吗?您不能只调用URL以触发远程脚本操作,然后丢弃它发送的任何数据吗? - Pekka
@Pekka:它不需要等待它完成。它所要做的就是发送GET数据,然后就可以关闭连接了。 - Rob
6个回答

6
有很多方法可以解决这个问题。您可以使用cURL和它的curl_multi_*函数异步执行请求,或者以普通方式使用cURL,但将超时限制设置为1,这样它将请求并返回超时,但是请求将被执行。
如果您没有安装cURL,可以继续使用file_get_contents,但使用forking进程(不太酷,但有效),例如ZendX_Console_Process_Unix,这样就避免了每个请求之间的等待。

是的,让我研究一下并玩弄几分钟。 - Rob
尝试了这个: $ch = curl_init($s['url']); //加载URL curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1); //只发送数据,不等待。 curl_exec($ch); //执行 curl_close($ch); //关闭它仍然在加载所有的URL。 - Rob
抱歉,我没有时间测试它。你可能想尝试其他方法。 - Franco

2
关于您更新的信息,只需要“触发”操作:
你可以尝试使用带有超时的file_get_contents。这将导致调用远程脚本,但连接在n秒后(例如1秒)被终止。
如果远程脚本被配置为即使连接中断也继续运行(在PHP中,这将是ignore_user_abort),它应该能够工作。
试一下。如果不起作用,您就不能避免增加time_limit或使用外部可执行文件。但从您所说的 - 您只需要发出请求 - 这应该可以工作。您甚至可以尝试将超时设置为0,但我不会相信那个。
来自这里
<?php
$ctx = stream_context_create(array(
    'http' => array(
        'timeout' => 1
        )
    )
);
file_get_contents("http://example.com/", 0, $ctx);
?>

公正地说,Chris的回答已经包括了这种可能性:curl也有一个超时开关。

我知道为什么下载需要这么长时间了,是因为我正在加载的页面需要花费30秒到5分钟的时间才能完全加载。 - Rob

2
如Franco所提及的,你需要使用curl_multi函数而不是常规的curl函数。这将多个curl对象打包到一个curl_multi对象中,并同时执行它们,随着响应的到达返回(或不返回,在你的情况下)响应。
示例请参见http://php.net/curl_multi_init

1

消耗时间的不是file_get_contents()函数,而是网络连接本身。
考虑不要将GET数据提交到一系列网站的数组中,而是创建一个RSS并让它们获取RSS数据。


如果有提供 feed 的话,最好的方法是使用 +1。但这会留下一些无法正常工作的站点,这可以通过 curl 来解决。 - Tim Post

1

我不完全理解你的脚本背后的含义。

但是你可以这样做:

  1. 为了快速避免致命错误,你可以在文件开头添加 set_time_limit(120)。这将允许脚本运行2分钟。当然,你可以使用任何你想要的数字,0表示无限。
  2. 如果你只需要调用URL而不关心结果,应该使用cUrl异步模式。在这种情况下,对URL的任何调用都不会等待它完成。你可以非常快地调用它们所有。

敬礼。


1

如果远程页面需要加载5分钟,那么您的file_get_contents会一直等待那5分钟。是否有办法修改远程脚本以分离为后台进程并在那里进行重型处理?这样,您的初始命中将几乎立即返回,而不必等待启动期。

另一个可能性是调查HEAD请求是否可行。 HEAD不返回任何数据,只返回头信息,因此它可能足以触发远程作业,而无需等待完整输出。


我喜欢HEAD的想法,也许值得一试。 - svens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接