CURL是一个非常强大的开源库,支持很多协议,包括HTTP、FTP、TELNET等,我们使用它来发送HTTP请求。它给我 们带来的好处是可以通过灵活的选项设置不同的HTTP协议参数,并且支持HTTPS。CURL可以根据URL前缀是“HTTP” 还是“HTTPS”自动选择是否加密发送内容。

使用CURL的PHP扩展完成一个HTTP请求的发送一般有以下几个步骤:

初始化连接句柄;
    设置CURL选项;
    执行并获取结果;
    释放CURL连接句柄。

一、使用curl模拟GET请求

$curl=curl_init();  //初始化curl句柄
$url="http://www.conglinfeng.com/together/detail.php?show_ID=5"; //要请求的url地址
curl_setopt($curl, CURLOPT_URL,$url); //设置curl的参数,即要请求的url是$url
curl_exec($curl); //执行操作
curl_close($curl); //关闭句柄

执行curl_exec()时,成功时会输出网页代码,并且返回值为 TRUE,在失败时返回 FALSE。 然而,如果 CURLOPT_RETURNTRANSFER选
项被设置,函数执行成功时会返回执行的结果,失败时返回 FALSE 。

二、使用curl模拟post请求

$curl=curl_init();
$url="./register.php";
curl_setopt($curl, CURLOPT_URL,$url);
curl_setopt($curl, CURLOPT_POST, true); //设置请求为post
$post_data=array('username'=>"嘿嘿",'password'=>'111111','confirm'=>'111111',
'email'=>"986992484@qq.com"); //要发送的数据组装成一个数组
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); //post的数据内容
curl_exec($curl);
curl_close($curl);

register.php:

var_dump($_POST);

三、处理响应的数据

curl_exec()执行时会直接把响应数据输出,如果不需要直接输出,可以加:curl_setopt($curl, CURLOPT_RETURNTRANSFER, true) ;

$url="./register.php";
curl_setopt($curl, CURLOPT_URL,$url);
curl_setopt($curl, CURLOPT_POST, true); //设置请求为post
$post_data=array('username'=>"嘿嘿",'password'=>'111111','confirm'=>'111111',
'email'=>"986992484@qq.com");
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); //post的数据内容
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true) ; //请求执行时,不将响应数据直接输出,而是以返回值的形式输出响应数据
$res=curl_exec($curl);
echo $res; //少了这句就输不出来了
curl_close($curl);

四、模拟post 文件上传

$url="./register.php";
curl_setopt($curl, CURLOPT_URL,$url);
curl_setopt($curl, CURLOPT_POST, true); //设置请求为post
$post_data=array('logo'=>'@D:\wamp\wamp\www\czbk\php&mysql\1.png'); // logo是$_FILES的name,后面的是图片路径,加@表示这是一个文件而不是字符串
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); //post的数据内容
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true) ; //请求执行时,不将响应数据直接输出,而是以返回值的形式输出响应数据
$res=curl_exec($curl);
echo $res;
curl_close($curl);

五、输出响应头

curl默认是不输出响应头的,如果要输出,则要加:curl_setopt($curl, CURLOPT_HEADER, true);

$url="http://www.conglinfeng.com/together/member/index.php";
curl_setopt($curl, CURLOPT_URL,$url);
curl_setopt($curl, CURLOPT_HEADER, true); //将响应头输出,默认是不输出的
// HTTP/1.1 200 OK Date: Thu, 15 Sep 2016 14:49:28 GMT Server: Apache/2.4.4 (Win32) PHP/5.4.16 X-Powered-By: PHP/5.4.16 Content-Length: 692 Content-Type: text/html
curl_exec($curl);
curl_close($curl);

六、实例:CURL模拟登陆

可以简单和有效地抓取网页并采集内容,设置cookie完成模拟登录网页,curl提供了丰富的函数,开发者可以从PHP手册中获取更多关于cURL信息。本文以模拟登录开源中国(oschina)为例,和大家分享cURL的使用。

PHP的curl()在抓取网页的效率方面是比较高的,而且支持多线程,而file_get_contents()效率就要稍低些,当然,使用curl时需要开启下curl扩展。

先来看登录部分的代码:

//模拟登录
function login_post($url, $cookie, $post) {
$curl = curl_init();//初始化curl模块
curl_setopt($curl, CURLOPT_URL, $url);//登录提交的地址
curl_setopt($curl, CURLOPT_HEADER, 0);//是否显示头信息
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);//是否自动显示返回的信息
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie); //设置Cookie信息保存在指定的文件中
curl_setopt($curl, CURLOPT_POST, 1);//post方式提交
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));//要提交的信息
curl_exec($curl);//执行cURL
curl_close($curl);//关闭cURL资源,并且释放系统资源
}

函数login_post()首先初始化curl_init(),然后使用curl_setopt()设置相关选项信息,包括要提交的url地址,保存的cookie文件,post的数据(用户名和密码等信息),是否返回信息等等,然后curl_exec执行curl,最后curl_close()释放资源。注意PHP自带的http_build_query()可以将数组转换成相连接的字符串。

接下来如果登录成功后,我们要获取登录成功后的页面信息。

//登录成功后获取数据
function get_content($url, $cookie) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); //读取cookie
$rs = curl_exec($ch); //执行cURL抓取页面内容
curl_close($ch);
return $rs;
}

函数get_content()中也是先初始化curl,然后设置相关选项,执行curl,释放资源。其中我们设置CURLOPT_RETURNTRANSFER为1即自动返回信息,而CURLOPT_COOKIEFILE可以读取到登录时保存的cookie信息,最后将页面内容返回。

我们的最终目的是要获取到模拟登录后的信息,也就是只有正常登录成功后才能获取的有用信息。接下来我们以登录开源中国的移动版为例,看看如何抓取到登录成功后的信息。

//设置post的数据
$post = array (
'email' => 'oschina账户',
'pwd' => 'oschina密码',
'goto_page' => '/my',
'error_page' => '/login',
'save_login' => '1',
'submit' => '现在登录'
); //登录地址
$url = "http://m.oschina.net/action/user/login";
//设置cookie保存路径
$cookie = dirname(__FILE__) . '/cookie_oschina.txt';
//登录后要获取信息的地址
$url2 = "http://m.oschina.net/my";
//模拟登录
login_post($url, $cookie, $post);
//获取登录页的信息
$content = get_content($url2, $cookie);
//删除cookie文件
@ unlink($cookie);
//匹配页面信息
$preg = "/<td class='portrait'>(.*)<\/td>/i";
preg_match_all($preg, $content, $arr);
$str = $arr[1][0];
//输出内容
echo $str;

七、封装CURL

为了便于日后调用,我们可以把这些操作封装起来。

1.模拟get或post请求

/**
* curl() curl模拟请求---一个参数是get请求,两个参数是post请求
*
* 上传文件$post=array('logo'=>'@D:\wamp\wamp\www\czbk\php&mysql\1.png');
* logo是$_FILES的name,后面的是图片路径,加@表示这是一个文件而不是字符串
*
* @param string $url 模拟请求的url
* @param array $post post请求时要提交的数据
* @param boolean $header 是否要将响应头输出
* @return string $str 返回响应结果
*/
function curl($url,$post=array(),$header=false){
if(!$url) return; //设置资源句柄
$curl=curl_init();
curl_setopt($curl, CURLOPT_URL,$url); //如果传$post,则说明是post请求
if($post && is_array($post) && count($post)>0){
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //不验证证书
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); //不验证证书
} //请求执行时,不将响应数据直接输出,而是以返回值的形式输出响应数据
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); //决定要不要将响应头输出
curl_setopt($curl, CURLOPT_HEADER,$header);
$str=curl_exec($curl); //IGNORE 忽略转换时的错误,如果没有ignore参数,所有该字符后面的字符串都无法被保存。
$str = iconv("UTF-8","GBK//IGNORE",$str);
curl_close($curl); return $str;
}

2.模拟登陆

/**
* curl_login() curl模拟登陆
*
* @param string $logUrl 登陆地址url
* @param string $desUrl 要访问页面的url
* @param array $post 要提交的数据
* @param string $cookie='' 存储cookie的文件路径
* @return string $str 返回响应结果
*/
function curl_login($logUrl,$desUrl,$post,$cookie=''){
/********模拟登陆**********/
//初始化curl模块
$curl = curl_init();
//登录提交的地址
curl_setopt($curl, CURLOPT_URL,$logUrl);
//是否显示头信息
curl_setopt($curl, CURLOPT_HEADER, 0);
//是否自动显示返回的信息
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);
//设置Cookie信息保存在指定的文件中
if(!$cookie) $cookie=dirname(__FILE__) . '/cookie.txt';
if(!file_exists($cookie))}{
$fp=fopen($cookie, 'w'); fclose($fp);
}
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie);
//post方式提交
curl_setopt($curl, CURLOPT_POST, 1);
//提交信息,http_build_query()可以将数组转换成相连接的字符串。
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
//执行cURL并关闭cURL资源,并且释放系统资源
curl_exec($curl);
curl_close($curl);
/********登陆后获取数据**********/
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $desUrl);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//读取cookie
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
$rs = curl_exec($ch); //执行cURL抓取页面内容
curl_close($ch);
return $rs;
}

也可以把curl的操作封装成一个类 Curl.class.php

<?php

/**
* CURL操作类,可用于模拟请求
* @author leshen <986992484@qq.com>
* @version 1.1
* usage:
* 1.设置选项
* $options=array(
* 'isReturn'=>true, //将响应结果返回。如果不想获取源码而是想渲染页面,请设置为false
* 'isHeader'=>true, //将响应头返回
* );
* $curl=new Curl($options);
* 2.模拟一般的get请求
* $curl=new Curl();
* $url="https://www.baidu.com";
* var_dump($curl->curl_get($url));
* 3.模拟需要盗链的get请求(查询四六级为例)
* $curl=new Curl();
* $url='http://www.chsi.com.cn/cet/query';
* $referer="http://www.chsi.com.cn/cet";
* $data=array('xm'=>'钟林生','zkzh'=>'360021161218718');
* $respn=$curl->curl_get_chain($url,$data,$referer);
* var_dump($respn);
* 4.模拟post请求(查询四六级为例)
* $data=array(
* 'name'=>'王勇平',
* 'province'=>'江西',
* 'school'=>'江西师范大学',
* 'type'=>'1'
* );
* $url='http://cet.zy62.com/query/2';
* $curl=new Curl();
* var_dump($curl->curl_post($url,$data));
*/ class Curl{ /**
* curl资源句柄
* @var resource
*/
private $curl; /*curl选项*/
private $isReturn; //是否将响应结果返回
private $isHeader; //是否将响应头返回
private $timeout; //超时时间
private $userAgent; //客户端代理
private $verifyPeer; //是否终止cURL从服务端进行验证
private $verifyHost; //检查服务器SSL证书中是否存在一个公用名 /**
* 构造方法,用于实例化一个curl对象
*/
public function __construct($options=array()){
/*初始化资源句柄*/
$this->curl=curl_init();
/*初始化curl选项*/
$this->isReturn=isset($options['isReturn'])?$options['isReturn']:ture;
$this->isHeader=isset($options['isHeader'])?$options['isHeader']:false;
$this->timeout=isset($options['timeout'])?$options['timeout']:30;
$this->userAgent=isset($options['userAgent'])?$options['timeout']:
isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 FirePHP/0.7.4';
$this->verifyPeer=isset($options['verifyPeer'])?$options['verifyPeer']:false;
$this->verifyHost=isset($options['verifyHost'])?$options['verifyHost']:2;
} /**
* 设置curl选项
* @param string $url 请求的url
* @param boolean $ssl 是否以https协议传输
* @return void
*/
private function setOption($url,$ssl){
/*设置curl选项*/
curl_setopt($this->curl, CURLOPT_URL, $url);//URL
curl_setopt($this->curl, CURLOPT_USERAGENT, $this->userAgent);//userAgent,请求代理信息
curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);//设置超时时间 /*SSL相关*/
if ($ssl) {
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER,$this->verifyPeer);//禁用后cURL将终止从服务端进行验证
curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST,$this->verifyHost);//检查服务器SSL证书中是否存在一个公用名(common name)。
} /*响应结果*/
curl_setopt($this->curl, CURLOPT_HEADER, $this->isHeader);//是否返回响应头
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, $this->isReturn);//curl_exec()是否返回响应结果
} /**
* 执行curl请求
* @return string 返回响应内容
*/
private function exec(){
/*发出请求*/
$response = curl_exec($this->curl);
if (false === $response) {
echo '<br>', curl_error($this->curl), '<br>';
return false;
}
curl_close($this->curl);
return $response;
} /**
* curl模拟post请求,返回响应的内容
* @param string $url 请求的url
* @param array $data 发送的数据,数组
* @param boolean $ssl 是否以https协议传输,默认为true
* @return string $response 返回响应的内容
*/
public function curl_post($url, $data, $ssl=true) {
/*设置选项*/
$this->setOption($url,$ssl); /*处理post相关选项*/
curl_setopt($this->curl, CURLOPT_POST, true);// 是否为POST请求
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $data);// 设置post的内容 /*执行curl请求*/
if($this->isReturn){
return $this->exec();
}
$this->exec();
} /**
* curl模拟一般的get请求,返回响应的内容
* @param string $url 请求的url,可以带查询参数
* @param boolean $ssl 是否以https协议传输,默认为true
* @return string $response 返回响应的内容
*/
public function curl_get($url,$ssl=true) {
/*设置选项*/
$this->setOption($url,$ssl); /*执行curl请求*/
if($this->isReturn){
return $this->exec();
}
$this->exec();
} /**
* curl模拟需要盗链的get请求,返回响应的内容
* @param string $url 请求的url
* @param array $data 查询参数,数组形式,方法内会自动转换为字符串形式
* @param string $referer 盗链的url
* @param boolean $ssl 是否以https协议传输,默认为true
* @return string $response 返回响应的内容
*/
public function curl_get_chain($url,$data,$referer,$ssl=true){
/*设置选项*/
$this->setOption($url,$ssl);
$param='';
foreach ($data as $k => $v) {
$param.= urlencode($k).'='.urlencode($v).'&';
}
/*设置查询参数*/
curl_setopt($this->curl, CURLOPT_POST, 0);
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $param); /*设置referer盗链*/
curl_setopt($this->curl, CURLOPT_REFERER, $referer); /*执行curl请求*/
if($this->isReturn){
return $this->exec();
}
$this->exec();
}
}

PHP使用CURL抓取网页的更多相关文章

  1. PHP CURL抓取网页 simple_html_dom类

    抓取网页数据后 数据录入到discuz中 <?php include('simple_html_dom.php'); function urlText(){ $url = 'http://www ...

  2. php使用curl抓取网页自动跳转问题处理

    问题分析: 请求抓取http://go.com数据: function curlGet($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, ...

  3. C语言调用curl库抓取网页图片

    思路是先用curl抓取网页源码,然后以关键字寻找出图片网址.   #include <stdio.h> #include <stdlib.h> #include <str ...

  4. C语言调用curl库抓取网页图片(转)

    思路是先用curl抓取网页源码,然后以关键字寻找出图片网址.  范例: #include <stdio.h> #include <stdlib.h> #include < ...

  5. php curl_multi系列函数实现多线程抓取网页

    最近几天在做一个多搜索引擎关键字排名查询工具,用于及时方便的了解关键词在各大搜索引擎的排名. 在抓取360搜索的时候,发现360搜索每页只支持显示10个搜索结果,如果想获取100个搜索结果数据,就得搜 ...

  6. curl抓取页面时遇到重定向的解决方法

    用php的curl抓取网页遇到了问题,为阐述方便,将代码简化如下: <?php function curlGet($url) { $ch = curl_init(); curl_setopt($ ...

  7. PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)

    通过curl_setopt()函数可以方便快捷的抓取网页(采集很方便),curl_setopt 是php的一个扩展库 使用条件:需要在php.ini 中配置开启.(PHP 4 >= 4.0.2) ...

  8. PHP利用Curl实现多线程抓取网页和下载文件

    PHP 利用 Curl  可以完成各种传送文件操作,比如模拟浏览器发送GET,POST请求等等,然而因为php语言本身不支持多线程,所以开发爬虫程序效率并不高,一般采集 数据可以利用 PHPquery ...

  9. PHP的cURL库:抓取网页,POST数据及其他,HTTP认证 抓取数据

    From : http://developer.51cto.com/art/200904/121739.htm 下面是一个小例程: ﹤?php// 初始化一个 cURL 对象$curl = curl_ ...

随机推荐

  1. OOP的魔术方法

    1.构造函数:__construct(): 构造函数是类中的一个特殊函数,当我们使用new关键字实例化对象时,相当于调用了类的构造函数. function __construct($name){ $t ...

  2. Java SE之快速失败(Fast-Fail)与快速安全(Fast-Safe)的区别[集合与多线程/增强For](彻底详解)

    声明 特点:基于JDK源码进行分析. 研究费时费力,如需转载或摘要,请显著处注明出处,以尊重劳动研究成果:博客园 - https://www.cnblogs.com/johnnyzen/p/10547 ...

  3. Ubuntu 划词翻译

    在 Windows 下用 QTranslate 可以划词翻译,调用谷歌或百度翻译引擎,不需要本地词典. 在 Ubuntu 下可以自己写脚本实现一个简陋的版本. 步骤如下: 安装 xsel,sudo a ...

  4. 利用YOLOV3训练自己的数据

    写在前面:YOLOV3只有修改了源码才需要重新make,而且make之前要先make clean. 一.准备数据 在/darknet/VOCdevkit1下建立文件夹VOC2007. voc2007文 ...

  5. selenium采用find_element_by方法识别页面元素

    主要是练习获取页面中的各元素,马克 # coding:utf-8 import time from selenium import webdriver import unittest from pyt ...

  6. nginx允许IP访问不生效问题【原创】

    使用nginx的nginx_upstream_check模块来检测后端服务器的转态时,设置只允许某段IP访问,发现不生效,不在此网段的IP也可以访问. 原因为在允许IP访问最后一定要加deny all ...

  7. python安装过程中的一些问题

    因为看到大神的教程是基于python V2.7,下载该版本且安装成功. 安装目录: https://www.python.org/download/releases/2.7/ 根据系统进行安装包下载 ...

  8. 【medium】990. Satisfiability of Equality Equations 并查集

    Given an array equations of strings that represent relationships between variables, each string equa ...

  9. Centos安装Git、DotNet、Docker

    1.安装Git yum install git 可通过下面的命令查看Git版本 git --version 2.安装Dotnet sudo yum install libunwind libicu 导 ...

  10. GIT----IDEA配置git

    配置git 创建本地厂库 可以选中项目所在的目录下 此时发现所有的页面的文件都变红,是因为变红的文件还没有add 添加提交的项目(add) 选中提交的文件右击,git ,add 如果想把整个项目都ad ...