php中使用Curl、socket、file_get_contents三种方法POST提交数据


Posted in PHP onAugust 12, 2011

抓取远程内容,之前一直都在用file_get_content函数,其实早就知道有curl这么一个好东西的存在,但是看了一眼后感觉使用颇有些复杂,没有file_get_content那么简单,再就是需求也不大,所以没有学习使用curl。
直到最近,要做一个网页小偷程序的时候才发现file_get_content已经完全不能满足需求了。我觉得,在读取远程内容的时候,file_get_content除了使用比curl便捷以外,其他都没有curl好。

php中curl和file_get_content的一些比较

主要区别:

学习才发现,curl支持很多协议,有FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE以及LDAP,也就是说,它能做到很多file_get_content做不到的事情。curl在php可以实现远程获取和采集内容;实现PHP网页版的FTP上传下载;实现模拟登陆;实现接口对接(API),数据传输;实现模拟Cookie;下载文件断点续传等等,功能十分强大。

了解curl一些基本的使用后,才发现其实并不难,只不过记住里面一些设置参数,难弄一点,但是我们记住几个常用的就可以了。

开启curl:

因为PHP默认是不支持curl功能的,因此如果要用curl的话,首先需要在php.ini中开启该功能,即去掉 ;extension= php_curl.dll 前面的分号,然后保存后重启apache/iis就好了。

基本语法:

$my_curl = curl_init();    //初始化一个curl对象
curl_setopt($my_curl, CURLOPT_URL, "https://3water.com");    //设置你需要抓取的URL
curl_setopt($my_curl,CURLOPT_RETURNTRANSFER,1);    //设置是将结果保存到字符串中还是输出到屏幕上,1表示将结果保存到字符串
$str = curl_exec($curl);    //执行请求
echo $str;    //输出抓取的结果
curl_close($curl);    //关闭url请求

最近需要获取别人网站上的音乐数据。用了file_get_contents函数,但是总是会遇到获取失败的问题,尽管按照手册中的例子设置了超时,可多数时候不会奏效:

$config['context'] = stream_context_create(array('http' => array('method' => "GET",
'timeout' => 5//这个超时时间不稳定,经常不奏效
)
));

这时候,看一下服务器的连接池,会发现一堆类似的错误,让我头疼万分:
file_get_contents(http://***): failed to open stream…

现在改用了curl库,写了一个函数替换:
function curl_file_get_contents($durl){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $durl);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_USERAGENT, _USERAGENT_);
curl_setopt($ch, CURLOPT_REFERER,_REFERER_);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$r = curl_exec($ch);
curl_close($ch);
return $r;
}

如此,除了真正的网络问题外,没再出现任何问题。
这是别人做过的关于curl和file_get_contents的测试:
file_get_contents抓取google.com需用秒数:

2.31319094
2.30374217
2.21512604
3.30553889
2.30124092

curl使用的时间:

0.68719101
0.64675593
0.64326
0.81983113
0.63956594

差距很大?呵呵,从我使用的经验来说,这两个工具不只是速度有差异,稳定性也相差很大。

建议对网络数据抓取稳定性要求比较高的朋友使用上面的 curl_file_get_contents函数,不但稳定速度快,还能假冒浏览器欺骗目标地址哦!

方法1: 用file_get_contents 以get方式获取内容

<?php
$url='http://www.domain.com/';
$html = file_get_contents($url);
echo $html;
?>

方法2: 用fopen打开url, 以get方式获取内容

<?php
$fp = fopen($url, 'r');
stream_get_meta_data($fp);
while(!feof($fp)) {
$result .= fgets($fp, 1024);
}
echo "url body: $result";
fclose($fp);
?>

方法3:用file_get_contents函数,以post方式获取url

<?php
$data = array ('foo' => 'bar');
$data = http_build_query($data);
$opts = array (
'http' => array (
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencodedrn" .
"Content-Length: " . strlen($data) . "rn",
'content' => $data
)
);
$context = stream_context_create($opts);
$html = file_get_contents('http://localhost/e/admin/test.html', false, $context);
echo $html;
?>

方法4:用fsockopen函数打开url,以get方式获取完整的数据,包括header和body

<?php
function get_url ($url,$cookie=false)
{
$url = parse_url($url);
$query = $url[path]."?".$url[query];
echo "Query:".$query;
$fp = fsockopen( $url[host], $url[port]?$url[port]:80 , $errno, $errstr, 30);
if (!$fp) {
return false;
} else {
$request = "GET $query HTTP/1.1rn";
$request .= "Host: $url[host]rn";
$request .= "Connection: Closern";
if($cookie) $request.="Cookie: $cookien";
$request.="rn";
fwrite($fp,$request);
while()) {
$result .= @fgets($fp, 1024);
}
fclose($fp);
return $result;
}
}
//获取url的html部分,去掉header
function GetUrlHTML($url,$cookie=false)
{
$rowdata = get_url($url,$cookie);
if($rowdata)
{
$body= stristr($rowdata,"rnrn");
$body=substr($body,4,strlen($body));
return $body;
}
return false;
}
?>

方法5:用fsockopen函数打开url,以POST方式获取完整的数据,包括header和body

<?php
function HTTP_Post($URL,$data,$cookie, $referrer="")
{
// parsing the given URL
$URL_Info=parse_url($URL);
// Building referrer
if($referrer=="") // if not given use this script as referrer
$referrer="111″;
// 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;
// building POST-request:
$request.="POST ".$URL_Info["path"]." HTTP/1.1n";
$request.="Host: ".$URL_Info["host"]."n";
$request.="Referer: $referern";
$request.="Content-type: application/x-www-form-urlencodedn";
$request.="Content-length: ".strlen($data_string)."n";
$request.="Connection: closen";
$request.="Cookie: $cookien";
$request.="n";
$request.=$data_string."n";
$fp = fsockopen($URL_Info["host"],$URL_Info["port"]);
fputs($fp, $request);
while(!feof($fp)) {
$result .= fgets($fp, 1024);
}
fclose($fp);
return $result;
}
?>

方法6:使用curl库,使用curl库之前,可能需要查看一下php.ini是否已经打开了curl扩展

<?php
$ch = curl_init();
$timeout = 5;
curl_setopt ($ch, CURLOPT_URL, 'http://www.domain.com/');
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$file_contents = curl_exec($ch);
curl_close($ch);
echo $file_contents;
?>

php中 curl, fsockopen ,file_get_contents 三个函数 都可以实现采集模拟发言 。三者有什么区别,或者讲究么

赵永斌:
有些时候用file_get_contents()调用外部文件,容易超时报错。换成curl后就可以.具体原因不清楚
curl 效率比file_get_contents()和fsockopen()高一些,原因是CURL会自动对DNS信息进行缓存(亮点啊有我待亲测)

范佳鹏:
file_get_contents curl fsockopen
在当前所请求环境下选择性操作,没有一概而论:
具我们公司开发KBI应用来看:
刚开始采用:file_get_contents
后来采用:fsockopen
最后到至今采用:curl

(远程)我个人理解到的表述如下(不对请指出,不到位请补充)
file_get_contents 需要php.ini里开启allow_url_fopen,请求http时,使用的是http_fopen_wrapper,不会keeplive.curl是可以的。
file_get_contents()单个执行效率高,返回没有头的信息。
这个是读取一般文件的时候并没有什么问题,但是在读取远程问题的时候就会出现问题。
如果是要打一个持续连接,多次请求多个页面。那么file_get_contents和fopen就会出问题。
取得的内容也可能会不对。所以做一些类似采集工作的时候,肯定就有问题了。
sock较底层,配置麻烦,不易操作。 返回完整信息。

潘少宁-腾讯:
file_get_contents 虽然可以获得某URL的内容,但不能post get啊。
curl 则可以post和get啊。还可以获得head信息
而socket则更底层。可以设置基于UDP或是TCP协议去交互
file_get_contents 和 curl 能干的,socket都能干。
socket能干的,curl 就不一定能干了
file_get_contents 更多的时候 只是去拉取数据。效率比较高 也比较简单。
赵的情况这个我也遇到过,我通过CURL设置host 就OK了。 这和网络环境有关系

<?php 
/** 
* Socket版本 
* 使用方法: 
* $post_string = "app=socket&version=beta"; 
* request_by_socket('3water.com','/restServer.php',$post_string); 
*/ 
function request_by_socket($remote_server,$remote_path,$post_string,$port = 80,$timeout = 30){ 
$socket = fsockopen($remote_server,$port,$errno,$errstr,$timeout); 
if (!$socket) die("$errstr($errno)"); 
fwrite($socket,"POST $remote_path HTTP/1.0"); 
fwrite($socket,"User-Agent: Socket Example"); 
fwrite($socket,"HOST: $remote_server"); 
fwrite($socket,"Content-type: application/x-www-form-urlencoded"); 
fwrite($socket,"Content-length: ".strlen($post_string)+8.""); 
fwrite($socket,"Accept:*/*"); 
fwrite($socket,""); 
fwrite($socket,"mypost=$post_string"); 
fwrite($socket,""); 
$header = ""; 
while ($str = trim(fgets($socket,4096))) { 
$header.=$str; 
} 
$data = ""; 
while (!feof($socket)) { 
$data .= fgets($socket,4096); 
} 
return $data; 
} 
/** 
* Curl版本 
* 使用方法: 
* $post_string = "app=request&version=beta"; 
* request_by_curl('http://3water.com/restServer.php',$post_string); 
*/ 
function request_by_curl($remote_server,$post_string){ 
$ch = curl_init(); 
curl_setopt($ch,CURLOPT_URL,$remote_server); 
curl_setopt($ch,CURLOPT_POSTFIELDS,'mypost='.$post_string); 
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); 
curl_setopt($ch,CURLOPT_USERAGENT,"Jimmy's CURL Example beta"); 
$data = curl_exec($ch); 
curl_close($ch); 
return $data; 
} 
/** 
* 其它版本 
* 使用方法: 
* $post_string = "app=request&version=beta"; 
* request_by_other('http://3water.com/restServer.php',$post_string); 
*/ 
function request_by_other($remote_server,$post_string){ 
$context = array( 
'http'=>array( 
'method'=>'POST', 
'header'=>'Content-type: application/x-www-form-urlencoded'."". 
'User-Agent : Jimmy's POST Example beta'."". 
'Content-length: '.strlen($post_string)+8, 
'content'=>'mypost='.$post_string) 
); 
$stream_context = stream_context_create($context); 
$data = file_get_contents($remote_server,FALSE,$stream_context); 
return $data; 
} 
?>
PHP 相关文章推荐
在线短消息收发的程序,不用数据库
Oct 09 PHP
php你的验证码安全码?
Jan 02 PHP
php中常用编辑器推荐
Jan 02 PHP
PHP 分页原理分析,大家可以看看
Dec 21 PHP
PHP与SQL注入攻击防范小技巧
Sep 16 PHP
非常好用的两个PHP函数 serialize()和unserialize()
Feb 04 PHP
PHP中使用BigMap实例
Mar 30 PHP
使用PHP接受文件并获得其后缀名的方法
Aug 05 PHP
php用正则判断是否为数字的方法
Mar 25 PHP
PHP获取不了React Native Fecth参数的解决办法
Aug 26 PHP
PHP并发查询MySQL的实例代码
Aug 09 PHP
PHP实现微信提现(企业付款到零钱)
Aug 01 PHP
PHP简洁函数小结
Aug 12 #PHP
不支持fsockopen但支持culr环境下下ucenter与modoer通讯问题
Aug 12 #PHP
PHP中获取内网用户MAC地址(WINDOWS/linux)的实现代码
Aug 11 #PHP
php 文章调用类代码
Aug 11 #PHP
初学PHP的朋友 经常问的一些问题。不断更新
Aug 11 #PHP
shopex中集成的站长统计功能的代码简单分析
Aug 11 #PHP
pdo中使用参数化查询sql
Aug 11 #PHP
You might like
PHP获取和操作配置文件php.ini的几个函数介绍
2013/06/24 PHP
php事务处理实例详解
2014/07/11 PHP
php获取汉字拼音首字母的方法
2015/10/21 PHP
jQuery仿Excel表格编辑功能的实现代码
2013/05/01 Javascript
vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据
2020/10/26 Javascript
jQuery中的on与bind绑定事件区别实例详解
2017/02/28 Javascript
详解Vue快速零配置的打包工具——parcel
2018/01/16 Javascript
vue柱状进度条图像的完美实现方案
2019/08/26 Javascript
vue使用swiper实现左右滑动切换图片
2020/10/16 Javascript
详解Vue 的异常处理机制
2020/11/30 Vue.js
Python实现各种排序算法的代码示例总结
2015/12/11 Python
Python模拟登陆淘宝并统计淘宝消费情况的代码实例分享
2016/07/04 Python
python实现基于SVM手写数字识别功能
2020/05/27 Python
Android基于TCP和URL协议的网络编程示例【附demo源码下载】
2018/01/23 Python
python3利用Dlib19.7实现人脸68个特征点标定
2018/02/26 Python
Python callable()函数用法实例分析
2018/03/17 Python
利用Python如何生成便签图片详解
2018/07/09 Python
对Python中class和instance以及self的用法详解
2019/06/26 Python
Django  ORM 练习题及答案
2019/07/19 Python
Python3爬虫里关于Splash负载均衡配置详解
2020/07/10 Python
使用javascript和HTML5 Canvas画的四渐变色播放按钮效果
2014/04/10 HTML / CSS
Vision Directa智利眼镜网:框架眼镜、隐形眼镜和名牌太阳眼镜
2016/11/23 全球购物
日本最大的药妆连锁店:Matsukiyo松本清药妆店
2017/11/23 全球购物
斯凯奇新西兰官网:SKECHERS新西兰
2018/02/22 全球购物
实习生个人找工作的自我评价
2013/10/30 职场文书
电气专业推荐信范文
2013/11/18 职场文书
家长给孩子的表扬信
2014/01/17 职场文书
巾帼文明岗申报材料
2014/05/01 职场文书
农林经济管理专业自荐信
2014/09/01 职场文书
拿破仑传读书笔记
2015/07/01 职场文书
开业庆典嘉宾致辞
2015/08/01 职场文书
女方家长婚礼答谢词
2015/09/29 职场文书
丧事酒宴答谢词
2015/09/30 职场文书
MySQL快速插入一亿测试数据
2021/06/23 MySQL
面试中老生常谈的MySQL问答集锦夯实基础
2022/03/13 MySQL
Win11 Beta 22621.601 和 22622.601今日发布 KB5017384修复内容汇总
2022/09/23 数码科技