一个php curl封装的类,减少代码量,简化采集工作。这个类也是我工作的最常用的类之一。这里分享给大家。配合上phpquery,十分好用。
<?php
namespace iphp\core;
use iphp\App;
/**
* 封装了的curl http请求类
* @author xuen
*/
class MyCurl
{
public $ch; // 当前链接对象
public $str = ''; // 当前串
public $match; // 正则表达式
/**
* 将curl常量属性转变成一个数组,便于使用
* @var string
*/
public $defaultOpt = array(
CURLOPT_URL => '', // 请求的URL
CURLOPT_RETURNTRANSFER => 1, // 设置有返回信息,以流的形式返回,非不是直接输出
CURLOPT_HTTPGET => 1, // 设定为GET请求。
// 定义默认的回调函数,这样exec()将在成功后返回1
CURLOPT_CONNECTTIMEOUT => 30, // 设置默认链接超时间为30秒
CURLOPT_TIMEOUT=>30,//设置下载时间最多30秒。
// 自动跟踪重定向。
CURLOPT_FOLLOWLOCATION => true,
// 设置客户端支持gzip压缩,默认不开启,用于节省流量。
CURLOPT_ENCODING => 'gzip',
// 设定默认header头
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.1; rv:23.0) Gecko/20100101 Firefox/23.0'
); public $opt; public $cookieFile = false; // 保存的COOKIE文件
/**
* http请求响应的缓存,默认缓存在数组中,最大为512个
* @var array
*/
public $cache = array(); public function __construct ()
{
// 完成CH的初始化
$this->ch = curl_init();
if (! $this->ch)
die('当前环境不支持CURL');
$this->opt=$this->defaultOpt;
}
// 执行HTTP请求,并得到返回数据
// 返回指定匹配的串,如果匹配失败将返回全部文档
public function exec ($opt)
{
//如查参数只是一个串,就认为是一个url
if(!is_array($opt))
{
$url=$opt;
$opt=array();
$opt['url']=$url;
}
// 如果存在缓存,则返回缓存的字符串。
$key = md5($opt['url'] . $opt['post'] . $opt['match']. $opt['return']);
if (($str = $this->getCache($key)) != false)
return $str;
// 每次执行前,清空当前str,每次请求,返回值可能不一样
$this->str = '';
// 参数设置失败和执行行失败都将返回 fasle;
if (! $this->setOptions($opt))
return false;
$flag = curl_exec($this->ch);
$this->setCache($key, $this->str ? $this->str : $flag); //执行完成后,基于长驻内存和考虑,上一次连接的选项可以对下一次靠成影响
$this->opt=$this->defaultOpt; if ($this->str == '') // 表示没有执行回调函数
return $flag;
else
return $this->str;
} /**
* 简单封装的file_get_contents函数
* 只是使用的缓存而已。
*/
public function getContent ($url)
{
$key = md5($url);
if (($str = $this->getCache($key)) != false)
return $str;
$str = file_get_contents($url);
$this->setCache($key, $str);
return $str;
}
// 设置CURL属性
public function setOptions ($opt)
{
foreach ($opt as $key => $value) {
// 以下值为可以设定的值。如果没有,将使用默认值;
switch ($key) {
case 'url': // 设定当前请求的URL
$this->opt[CURLOPT_URL] = $value;
break;
case 'str': // 设定信息返方式,默认为1
$this->opt[CURLOPT_RETURNTRANSFER] = $value;
break; // 默认值也为1
case 'method': // 设定请求方式,默认为POST
if ($value == 'get')
$this->opt[CURLOPT_HTTPGET] = 1; // 设为GET请求
elseif ($value == 'put')
$this->opt[CURLOPT_PUT] = 1; // ftp文件上传
else
$this->opt[CURLOPT_POST] = 1;
break;
case 'post': // 设定POST请求主体,数组形式,如果上传文件,文件名前加@
$this->opt[CURLOPT_POSTFIELDS] = $value;
break;
case 'header': // 设定HEADER请求头;默认不使用,数组形式
$this->opt[CURLOPT_HTTPHEADER] = $value;
break;
case 'referer': // 设定REFERER信息,默认为空
$this->opt[CURLOPT_REFERER] = $value;
break;
case 'auth': // 设定要请求的用户密码[username]:[password]
$this->opt[CURLOPT_USERPWD] = $value;
break;
case 'connect_time': // 发起链接前的等待时间
$this->opt[CURLOPT_CONNECTTIMEOUT] = $value;
break;
case 'load_time'://文件下载最长时间。
$this->opt[CURLOPT_TIMEOUT]=$value;
break;
case 'callback': // 定义回调函数
$this->opt[CURLOPT_WRITEFUNCTION] = $value;
break;
case 'match': // 寻找指定段的正则表达式
$this->opt[CURLOPT_WRITEFUNCTION] = array(
'self',
'callback'
);
$this->match = $value;
case 'proxy':
$this->opt[CURLOPT_PROXY] = $value;
break;
case 'file': // 用FTP上传的文件名柄
$this->opt[CURLOPT_VERBOSE] = 1;
$this->opt[CURLOPT_INFILE] = $value; // 上传句柄
$this->opt[CURLOPT_NOPROGRESS] = false;
$this->opt[CURLOPT_FTP_USE_EPRT] = true;
$this->opt[CURLOPT_FTP_USE_EPSV] = true;
break;
case 'cookie_file': // 设置cookie文件。
$this->cookieFile =APP_PATH . '/runtime/cookie.txt';
// 发送COOKIE
$this->opt[CURLOPT_COOKIEFILE] = $this->cookieFile;
// 设置cookie
$this->opt[CURLOPT_COOKIEJAR] = $this->cookieFile;
break;
case 'cookie'://设置访问cookie为一个字符串
$this->opt[CURLOPT_COOKIE]=$value;
break;
case 'return': // 设定返回的类型
if ($value == 'head') // 表示只得到header头
{
$this->opt[CURLOPT_NOBODY] = 1;
$this->opt[CURLOPT_HEADER] = 1;
}
elseif ($value == 'body') {}// 默认值,只返回body体
elseif ($value == 'all')
$this->opt[CURLOPT_HEADER] = 1;
break;
case 'location'://是不是跟踪重定向
$this->opt[CURLOPT_FOLLOWLOCATION]=$value;
break;
case 'client_type'://设定客户端类型
$this->setClientType($value);
break;
case 'client_ip'://设定客户端IP地址,只是在header头,不是真实伪造
$this->opt[CURLOPT_HTTPHEADER][]='X-FORWARDED-FOR: '.$value;
$this->opt[CURLOPT_HTTPHEADER][]='CLIENT-IP: '.$value;
break;
}
}
// 设定当前链接选项,选项设置失败返回false;
return curl_setopt_array($this->ch, $this->opt);
}
// 回调函数,返回指定正则表达式的HTML段
public function callback ($ch, $str)
{
$this->str .= $str;
preg_match($this->match, $this->str, $match);
if (! empty($match))
{
// 存在一个子模式,则返回这个子模式
if (isset($match[1]))
$this->str = $match[1];
else
$this->str = $match[0];
return false; // 中断请求
}
return strlen($str);
} /**
* 得到当前请求的错误信息
* @param int $type
* 0表示得到错误编码,1表示得到错误信息,2表示得到所有信息
* @return mixed
*/
public function getError ($type = 11)
{
switch ($type) {
case 0:
$info = curl_errno($this->ch);
break;
case 1:
$info = curl_error($this->ch);
break;
default:
$info = curl_getinfo($this->ch);
}
return $info;
} /**
* 清除缓存。
*/
public function __destruct ()
{
curl_close($this->ch);
$this->cache = array();
} /**
* 设置缓存,以减少http请求数量。
* 大量采集中,你应改使用重写此方法。
* 默认将使用内存缓存
* 如果缓存数组超过512个,清空数组缓存。
* @param string $key
* @param string $str
* @return string boolean
*/
public function setCache ($key, $str)
{
if(count($this->cache)>512)
$this->cache=array();
$this->cache[$key] = $str; //如果引入的phpquery对象
if(class_exists('\\phpQuery') && count(\phpQuery::$documents)>512)
\phpQuery::$documents=array();
} /**
* 得到缓存数据
*
* @param string $key
* @return string boolean
*/
public function getCache ($key)
{
if ($this->cache[$key])
return $this->cache[$key];
else
return false;
}
/**
* 调用远程http接口,返回一个数组
* 当前只支持get请求
* @param string $url
* @param array $query get方式查询参数
* 其中两个参数为自定义参数
* _method:为请求的类型
* _type:为返回的数据类型,支持xml,json.
* 这两个参数不做查询字符串
* @param array $type 返回的格式类型
*/
public function getArray($url,$query=array())
{
$method=($query['_method']=='post')?'post':'get';
$type = ($query['_type']=='xml')?'xml':'json';
if($query['_method'])
unset($query['_method']);
if($query['_type'])
unset($query['_type']);
if($method=='get')
{
if($query)
$nowUrl=$url.'?'.http_build_query($query);
else
$nowUrl=$url;
$str=$this->exec(array(
'url'=>$nowUrl,
'method'=>'get',
));
}
else
$str=$this->exec(array(
'url'=>$url,
'method'=>'post',
'post'=>$query
));
if(!$str)
return false;
$arr=$this->toArray($str,$type);
if(!$arr || !is_array($arr))
return false;
return $arr;
}
/**
* 将一个{}格式的javasrcipt对象转变成一个php数组
* 以避免过多的使用正则表达式。
* 目前支持一维数组;
* 如果js对像里面还有一个对象。可能会有问题。
* 通常情况下,你应该在页面中只匹配一个JS对象。
* @param string $str
* @return array|bool
*/
public function jsArray($str)
{
$return=array();
$str=str_replace(array(
'"',
"'",
'{',
'}'
), '', $str);
$arr=explode(',', $str);
foreach($arr as $row)
{
$tmpArr=explode(':', $row);
$return[trim($tmpArr[0])]=trim($tmpArr[1]);
}
return $return;
}
/**
* 使用phpquery来进行html页面采集
* @param unknown $str 字符串
* @param string $query 选择器表达式
* @return \phpQuery
*/
public function getDom($str,$query='')
{
require_once APP_PATH.'/iphp/extension/phpQuery/phpQuery.php';
$domObject=\phpQuery::newDocument($str);
if($query=='')
return $domObject;
return pq($query);
} /**
* 将字符串转变成一个数组;
* @param string $str 字符串
* @param string $type 类型。
* @return array|bool
*/
public function toArray($str,$type="json")
{
if($type=='xml')
{
$doc=simplexml_load_string($str);
$xml=App::getApp()->getXml();
return $xml->getTreeArray($doc);
}
elseif($type=='json')
return json_decode($str,true);
elseif($type=='query')
{
$parse=parse_url($str);
parse_str($parse['query'],$params);
return $params;
}
elseif($type=='pathinfo')
{ }
} /**
* 根据type类型默认浏览器客户端
* @param type $type
* iphone 表示iphone客户端,
* pc 表示电脑客户客户端,
* android 表示安卓客户端
*/
public function setClientType($type)
{
$userAgent=array(
'pc'=>'Mozilla/5.0 (Windows NT 6.1; rv:23.0) Gecko/20100101 Firefox/23.0',
'iphone'=>'Mozilla/5.0 (iPad; U; CPU OS 3_2_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B500 Safari/531.21.10',
'android'=>'Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'
);
if(array_key_exists($type,$userAgent))
$this->opt[CURLOPT_USERAGENT]=$userAgent[$type];
} //关闭当前资源连接
public function close()
{
curl_close($this->ch);
}
}
使用示例:
<?php namespace iphp\collect\live; use iphp\common\MyFunctions; /**
* 基于http://m.iqilu.com/的直播地址解析
* 只有流畅一个清晰度。
*
* @author 123
*
*/
class Iqilu extends LiveBase {
// 入品地址,可以得到频道列表
public $listUrl = 'http://v.iqilu.com/live/sdtv/';
public $sourceName = 'iqilu';
public function getList() {
$lists = array (
0 => array (
'sdtv',
'98/0',
'山东卫视'
),
1 => array (
'qlpd',
'98/1',
'齐鲁频道'
),
2 => array (
'ggpd',
'98/2',
'公共频道'
),
3 => array (
'typd',
'98/3',
'体育频道'
),
4 => array (
'shpd',
'99/2',
'生活频道'
),
5 => array (
'zypd',
'100/0',
'综艺频道'
),
6 => array (
'nkpd',
'99/0',
'农科频道'
),
7 => array (
'yspd',
'99/3',
'影视频道'
),
8 => array (
'sepd',
'99/1',
'少儿频道'
),
9 => array (
'gjpd',
'100/1',
'国际频道'
)/*,
10 => array (
'dspd',
'107/6',
'读书频道'
) */
);
foreach ( $lists as $item ) { $vid = $item [0] . ',' . $item [1] . ',' . $item [2];
$channel_name = $item [2];
$link = $this->getAll ( $vid ); $this->info [] = array (
'channel_name' => $channel_name,
'channel_link' => $link
);
}
return $this->info;
}
public function one($vid, $format) {
$arr2 = explode ( ',', $vid );
if ($format != 1) {
return false;
} $url = "http://huodong.iqilu.com/active/video/clientnew/public_s/?c="; $str = $this->curl->exec ( array (
'url' => $url . $arr2 [0],
'header' => array (
'Host: huodong.iqilu.com',
//'User-Agent: Android',
//"Referer: http://v.iqilu.com/live/{$arr2[0]}/",
'User-Agent: Mozilla/5.0 (Linux; U; Android 4.4.2; zh-CN; Coolpad 8675 Build/KOT49H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/9.9.7.500 U3/0.8.0 Mobile Safari/534.30',
),
'referer' => "http://m.iqilu.com/vms/live/{$arr2[0]}/",
'client_type' => "android" ) );
$arr = explode('|', $str);
$vid = "http://m3u8.iqilu.com/live/$arr2[1].m3u8?st=".$arr[16].$arr[17]."&e=".$arr[19].$arr[20];//&e={$arr[17]}; return $vid;
}
}