php抓取网页连接函数(本文_get_contents、fsockopen、curl、stream在php中的使用方法)
优采云 发布时间: 2022-03-26 14:04php抓取网页连接函数(本文_get_contents、fsockopen、curl、stream在php中的使用方法)
本文主要讲一下php中file_get_contents、fsockopen、stream_context_create、curl的使用以及它们适合的使用场景。
1、使用file_get_contents的get方法获取
$url = 'http://sobird.me/';
$result= file_get_contents($url);
2、使用file_get_contents的post方法获取
$postdata = http_build_query($data);
$options= array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
注:file_get_contents 需要php.ini里开启allow_url_fopen,allow_url_include 方可使用
3、用fopen打开url,用get获取
$fp = fopen($url, 'r');
stream_get_meta_data($fp);
$result = '';
while(!feof($fp)){
$result .= fgets($fp, 1024);
}
echo $result;
fclose($fp);
4、使用fsockopen函数打开url,在get方法中获取完整的数据,包括header和body
$query = '?test=test';
$host = 'sobird.me';
$port = 80;
$timeout = 30;
if (!$fp = @fsockopen($host, $port, $errno, $errstr, $timeout)) {
// Set error message
switch($errno) {
case -3:
$errormsg = 'Socket creation failed (-3)';
case -4:
$errormsg = 'DNS lookup failure (-4)';
case -5:
$errormsg = 'Connection refused or timed out (-5)';
default:
$errormsg = 'Connection failed ('.$errno.')';
$errormsg .= ' '.$errstr;
}
}
$request = "GET $query HTTP/1.1\r\n";
$request .= "Host: $host\r\n";
$request .= "Connection: Close\r\n";
$request.="\r\n";
fwrite($fp,$request);
$result = '';
while(!feof($fp)){
$result .= @fgets($fp, 1024);
}
fclose($fp);
echo $result;
5、使用fsockopen函数打开url,通过POST获取完整数据,包括header和body
$url = 'http://sobird.me/';
function HTTP_Post($URL,$data,$cookie, $referer=""){
// parsing the given URL
$URL_Info = parse_url($URL);
// making string from $data
foreach($data as $key=> $value)
$values[]="$key=".urlencode($value);
$data_string=implode("&",$values);
// Find out which port is needed - if not given use standard (=80)
if(!isset($URL_Info["port"]))
$URL_Info["port"]=80;
$request = '';
// building POST-request:
$request.="POST ".$URL_Info["path"]." HTTP/1.1\n";
$request.="Host: ".$URL_Info["host"]."\n";
$request.="Referer: $referer\n";
$request.="Content-type: application/x-www-form-urlencoded\n";
$request.="Content-length: ".strlen($data_string)."\n";
$request.="Connection: close\n";
$request.="Cookie: $cookie\n";
$request.="\n";
$request.=$data_string."\n";
$fp = fsockopen($URL_Info["host"],$URL_Info["port"]);
fputs($fp, $request);
$result = '';
while(!feof($fp))
{
$result .= fgets($fp, 1024);
}
fclose($fp);
return $result;
}
$data = array(
'test'=>'test'
);
$cookie = '';
$referer = 'http://sobird.me/';
echo HTTP_Post($url, $data, $cookie, $referer);
6、使用curl库,打开url,通过get获取
$url = 'http://sobird.me/';
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 5);
$file_contents = curl_exec($ch);
curl_close($ch);
echo $file_contents;
7、使用curl库,打开url,通过post获取
$url = 'http://sobird.me/';
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'test=test');
$file_contents = curl_exec($ch);
curl_close($ch);
echo $file_contents;
关于 curl 和 fsockopen。
fsockopen是比较底层的调用,属于网络系统的socket调用,curl的封装支持HTTPS认证、HTTP POST方式、HTTP PUT方式、FTP上传、kerberos认证、HTTP上传、代理服务器、cookies ,用户名/密码认证,下载文件续传,上传文件续传,http代理服务器管道(代理隧道),甚至支持IPv6,socks5代理服务器,通过http代理服务器上传文件到FTP服务器等,功能是很强大 。fsockopen 返回的是未处理的数据,包括数据的长度、数据的内容、数据的结束符。而curl是处理后的内容。
用户使用的时候,curl比较方便,但是参数比较多,配置稍微复杂一点,而fsockopen固定参数比较少,比较简单,但是结果可能需要处理。
关于 file_get_contents
有时使用 file_get_contents() 调用外部文件很容易出现超时和错误。curl 比 file_get_contents() 和 fsockopen() 更有效,因为 CURL 会自动缓存 DNS 信息。
file_get_contents/curl/fsockopen 在当前请求的环境中选择性地操作,没有一概而论。
file_get_contents 需要在 php.ini 中启用 allow_url_fopen。请求 http 时,使用 http_fopen_wrapper。如果 keeplive 不可用,可以使用 curl。file_get_contents() 单次执行效率很高,并且返回没有标题的信息。
这在读取一般文件的时候是没有问题的,但是读取远程的时候可能会出现问题。如果要建立持久连接,请多次请求多个页面。那么file_get_contents和fopen就会出现问题。获得的内容也可能不正确。所以在做采集之类的工作时,肯定是有问题的。
fsockopen的底层可以设置为基于UDP或TCP协议交互,配置麻烦,操作困难。返回完整信息。
总之,file_get_contents和curl可以做到,socket可以做到。套接字有能力,但 curl 可能没有能力。file_get_contents 更多时候只是为了提取数据。高效且简单。
如果我们只讨论curl和file_get_contents,有一些结论:
fopen /file_get_contents 将对每个请求重新进行 DNS 查询,并且不缓存 DNS 信息。但是 CURL 会自动缓存 DNS 信息。对同一域名下的网页或图片的请求只需要一次 DNS 查询。这大大减少了 DNS 查询的数量。所以 CURL 的性能比 fopen /file_get_contents 好很多。当 fopen /file_get_contents 请求 HTTP 时,它使用 http_fopen_wrapper,而不是 keeplive。卷曲可以。这样,当多次请求多个链接时,curl 会更高效。fopen/file_get_contents 函数受 php.ini 文件中的 allow_url_open 选项配置的影响。如果关闭配置,该功能也会失效。并且 curl 不受此配置的影响。curl可以模拟各种请求,例如:POST数据、表单提交等,用户可以根据自己的需要自定义请求。而 fopen/file_get_contents 只能使用 get 方法获取数据。
PS:file_get_contents()函数获取https链接内容时,需要php中mod_ssl的支持(或者安装opensll)。
结论是curl的效率和稳定性比file_get_contents()要好,fsockopen也很强大,但是比较低级。
参考: