编 写:袁 亮 时 间:2015-07-17 说 明:curl番外:linux命令行下使用 一、常用命令 1、直接抓取网页 curl http://www.ci123.com 2、抓取数据,并保存成文件 curl -O http://192.168.0.62/yl/curl/demo.php //需要后面有具体文件名,否则抓取不到 curl -o index.html http://www.ci123.com 3、仅显示http响应头 curl -I http://www.ci123.com 4、发送post数据 4.1 普通post curl -d "username=name&nickname=暗夜御林" http://192.168.0.62/yl/curl/demo.php 4.2 上传文件的时候,-F每次只能设置一个参数项,不能多个,文件名用@符号加载地址前 curl -F "file=@51268106.html" -F "username=name" -F "nickname=暗夜御林" http://192.168.0.62/yl/curl/demo.php 5、模拟登陆,使用cookie文件夹 5.1 将cookie写入到本地文件(使用-F可以) curl -c cookie.txt http://192.168.0.62/yl/curl/demo.php curl -D cookie.txt http://192.168.0.62/yl/curl/demo.php //直接将响应头存储进文件 5.2 使用本地存储的cookie文件发送请求 curl -b cookie.txt http://192.168.0.62/yl/curl/demo.php 6、伪造referer curl -e 'http://www.baidu.com' http://192.168.0.62/yl/curl/demo.php 7、使用代理访问(找免费代理,翻墙出去,google搜索比较给力) curl -x 124.202.183.170:8118 http://www.baidu.com
标签: php
fsockopen初阶:了解并使用
编 写:袁 亮
时 间:2015-07-16
说 明:fsockopen初阶:了解并使用
一、作用(简单使用)
1、类似file_get_contents,curl,在程序中,发起一次网络请求,抓取数据或者调用接口等
2、curl能干的事,这个也都能干
3、在发起http请求的时候,会对http整个工作过程更熟悉,每一步都很清楚
二、工作流程
1、使用fsockopen打开一个网络连接或者一个Unix套接字连接
2、使用fwrite,传输请求头信息
3、使用fgets读取响应
4、使用fclose关闭套接字
ps:一个完整的http请求,更清晰些,平时访问网页的时候,浏览器帮我们做的这些工作
三、使用条件
1、php配置中开启 allow_url_fopen
四、简单范例,php.net
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)
\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
五、函数封装
header("Content-Type:text/html;charset=utf-8;");
$data = fsockOpenHttp("http://local.ci123.com/yl/fsockopen/t.php",'POST',array('username'=>'yuanliang847','nickname'=>'暗夜御林'));
var_export($data);
//图片上传的暂未封装,可以自己看下firebug中上传图片时的请求信息,然后封装
function fsockOpenHttp($url, $method='GET', $postfields = NULL , $multi = false){
$url = trim($url);
if(!$url){
return array('status'=>4001,'mess'=>'链接不能为空');
}
$urlinfo = parse_url($url);
if(!$urlinfo['host']){
return array('status'=>4002,'mess'=>'链接非法,请填写完整链接地址');
}
if($urlinfo['scheme'] == 'https'){//判断是否是https请求
$port = 443;
$version = '1.1';
$host = 'ssl://'.$urlinfo['host'];
}else{
$port = 80;
$version = '1.0';
$host = $urlinfo['host'];
}
$urlinfo['path'] = $urlinfo['path']?$urlinfo['path']:'/';
$header = "{$method} {$urlinfo['path']} HTTP/$version\r\n";
$header .= "Host: {$urlinfo['host']}\r\n";
if($multi){
//$header .= "Content-Type: multipart/form-data; boundary=\r\n";
}else{
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
}
if(strtolower($method) == 'post' ){
if(is_array($postfields)){
$postfields = http_build_query($postfields);
}
$header .= "Content-Length: ".strlen($postfields)."\r\n";
$header .= "Connection: Close\r\n\r\n";
$header .= $postfields;
}else{
$header .= "Connection: Close\r\n\r\n";
}
$ret = '';
$fp = fsockopen($host,$port,$errno,$errstr,30);
if(!$fp){
return array('status'=>4003,'mess'=>'建立sock连接失败');
}
fwrite ($fp, $header);
while (!feof($fp)) {
$ret .= fgets($fp, 4096);
}
fclose($fp);
$info = split("\r\n\r\n",$ret);
$t = array_slice($info,1);
$returnInfo = implode('',$t);
$head = $info[0];
$tmp = split("\r\n", $head);
$tmp = split(" ", $tmp[0]);
$http_status = $tmp[1];
$html = iconv("utf-8","utf-8//ignore",$returnInfo);
return array(
'status' => '1',
'mess' => '请求成功',
'http_status'=> $http_status,//http响应头
'head' => $head,//完整返回头
'data' => $html//响应内容
);
}
http basic认证的那些事
编 写:袁 亮
时 间:2015-07-13
说 明:http basic认证的那些事
一、什么是http basic认证?
1、由http协议规定
2、提供简单的用户验证功能,适合于对安全性要求不高的地方
3、通过在http头部增加
Authorization: Basic username:password
的方式,来向服务端证明自己是一个被授权访问的用户
4、优点:
简单、方便
5、缺点:
安全性太低,账号密码容易泄露,而且不方便升级维护
6、替代协议
oauth,使用oauth可以提供更安全的授权访问,但是实现较复杂
现有oauth已经到了2.0版本,有兴趣的可以去了解下
二、常见使用方式
1、最熟悉的,应该是大家家里的路由器登陆页面,那就是一个典型的http basic认证
2、一些比较旧的项目后台,也会有这种登陆方式
3、自己写一些临时后台,又不想介入复杂的账号体系的话,也可以使用该验证方式
三、工作流程
1、浏览器第一次访问,没有带上相应账号密码请求
2、服务器端,判断如果没有带上相应请求头Authorization: Basic,则返回401状态码,以及
WWW-Authenticate:Basic realm="验证输入框标题"
3、浏览器收到401状态码,弹出各浏览器自行实现的账号、密码输入框供用户输入
4、浏览器将用户输入的用户和密码拼接,并加入到请求头中
Authorization: Basic base64_encode(username:password)
5、服务端将内容解析出来,并与自己的账号密码库比对,如果失败,继续要求填写账号密码
如果正确,则继续访问,并在之前的每次访问都带上相应的请求头
四、几种实现方式
1、apache设置【主要使用】
1.1 开启设置,在httpd.conf文件中,相应目录上设置(需要重新apache服务)
AuthType Basic
AuthName "请输入你的账号密码"
AuthUserFile .htpasswd #账号密码存储文件位置
Require valid-user #账号文件中的所有用户都可访问
1.2 添加账号
/opt/ci123/apache/bin/htpasswd -m /opt/ci123/www/html/geekman/.htpasswd username
//注意,第一次添加需要加-cm参数创建文件,之前不允许加-c,否则会直接覆盖那个文件,导致其他账号丢失
1.3 修改密码,同添加
1.4 删除账号,找到对应的账号文件,直接删除那一行即可
2、php设置,弹出
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
die;
} else {
echo "Hello {$_SERVER['PHP_AUTH_USER']}.
";
echo "You entered {$_SERVER['PHP_AUTH_PW']} as your password.
";
//验证该账号密码是否在允许范围内
}
五、程序模拟访问带http basic的页面
1、两种请求方式
1.1 将账号密码拼接在链接中
http://username:password@192.168.0.249/memadmin/basic.php
1.2 请求头中增加
Authorization: Basic base64_encode(username:password)
2、curl模拟账号密码
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, username:password);
3、rpc接口
初始化的时候,第三、第四个参数分别填用户名密码即可
curl:抓取https数据
编 写:袁 亮 时 间:2015-07-15 说 明:使用curl抓取https数据 一、为什么需要? 未了安全考虑,很多网站使用了https域名 https需要客户端和服务端都做openssl的验证 二、抓取设置 1、方法一,设置为不验证证书【直接用这个,除非安全性要求特别高】 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); ps:抓百度的时候需要注意,referer设置为百度本身的返回会又问题,可以自己尝试看看 2、设置一个正确的证书验证 2.1 下载最新的证书到本地 wget http://curl.haxx.se/ca/cacert.pem 2.2 设置使用证书 curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,true); ; curl_setopt($ch,CURLOPT_CAINFO,dirname(__FILE__).'/cacert.pem'); 三、一些错误情况(出错的情况下,开启curl_error($ch)查看) 1、centos系统,如果不知道证书地址,则使用系统证书 /etc/pki/tls/certs/ca-bundle.crt 2、如果系统证书过期,或者错误,则会显示签名出错 通过wget http://curl.haxx.se/ca/cacert.pem 来更新最新的证书 3、显示“段错误”,有可能是libcurl和php版本不一致导致 线上centos 6.2和php 5.2.17,出现过该问题 4、当不能确定是否是某台服务器出问题的时候,写个简单的demo,分别在几台服务器运行看下是否有问题 四、尚未解决 1、采用浏览器下载或者导出的证书,在程序中一直未能使用成功
简单MVC框架知识
编 写:袁 亮 时 间:2015-07-13 说 明:简单MVC框架知识 一、框架的优缺点 1、优点: 1.1 合作的人越来越多,使用框架,可以更好的划分不同部分,合作更方便 1.2 有些东西,不需要重复造轮子,直接使用别人做好的框架,比如rewrite、数据库操作、缓存等等 1.3 接受新项目,可以更快的上手,如果大家都按框架的要求来开发 1.4 安全性较高,比起裸写程序,很多框架,都对常规安全性问题进行了处理 2、缺点: 2.1 除了学习php之外,还需要学习框架的相关知识,更可怕的是大家都没花这个时间去学习, 导致使用了框架,但都没按框架的规则来写,维护这种项目就是个悲剧 2.2 因为框架开源,而且太多人使用,因此会出现一些框架本身的漏洞,很容易被人用机器扫描漏洞,造成安全隐患 2.3 性能比直接写会低一些,不过这个性能差距,可以忽略 二、MVC框架是什么? 1、MVC是为实现代码组织的一种策略,实现框架有很多种,MVC是使用最广的(MTV,MVP,CBD,ORM等) 2、M:model层,可以理解为是我们的类库,函数库,我们封装的一些工具 V:view层,显示层,最终展示给用户看的内容,由这一层决定 C:controller层,控制层,决定调用哪些model,进行哪些判断,获取什么数据,加载什么样的显示view显示 三、公司常用php框架(都是MVC模式的) 1、CodeIgniter 电商在用,轻量级,感觉还行 2、CakePhp 博客后台,ask,圈圈等很多项目在用,轻量级,挺不错的,只是我们很多老项目用错了,必须掌握 3、ThinkPhp 用的不多 4、Discuz 快速搭建论坛的首选,城市站等在用 5、Zend 用户中心,太重了,而且用户中心用的很乱,一般项目,不要选择这个 6、公司内部框架,博客,圈圈,宝宝主页,试用等一大批项目在用 四、附录: 1、模板语言smarty(非框架),了解即可,没必要使用 这个主要就是为了让前端不用学php代码,就可以直接写view层来设计的 但我个人觉得,学smarty的语法,并不比学php的简单语法更简单,完全没意义 还增加后端学习smarty语法的成本,并且最终还是要把smarty语法转出php语法的,性能也差
两种生成缩略图策略
编 写:袁 亮
时 间:2015-07-13
说 明:生成缩略图的两种策略
一、为什么需要压缩图片?
1、在各种web应用中,上传头像是一个非常常见的功能,比如头像、比如相册等等
2、用户上传的图片一般都很大,现在的手机拍的图片,基本上都是2-3M,如果是相机,6-7M,10来M也很正常
3、10M的图片,按现在用户的平均网速8M来说,那就是10MB/8Mb/s=10*8Mb/(8Mb/s)=10秒,浏览器显示一张照片就需要10秒,完全不能接受
4、一个网页或者界面,一般都会显示很多张图片,而且每张图片其实只显示了一个很小的尺寸
5、带宽费用很贵,因此图片显示,99%的地方都是显示的缩略图
二、两种压缩图片策略(图片不变形,变形的压缩不考虑,线上不允许使用)
1、将原图压缩生成一个指定宽高的图片
1.1 常见于头像等地方
1.2 生成的图片宽高固定,图片可能被裁减,很多时候需要使用js插件,让用户拖拽,确定裁减到什么位置
2、将原图压缩,宽高分别不能搞过某个值
2.1 相册等大多数情况
2.2 图片不会被裁减,但是生成出来的图片宽高不确定
三、php具体实现裁减
//引用php函数
include_once("image_function.php");
$old_src = '6.jpg';
$new_src = 'tmp/2013/02/27/2.jpg';
$new_width = 400;
$new_height = 300;
mkdir('tmp/2013/02/27',777,1);
1、方案1
$res = cutPhotoDesign($old_src,$new_src,$new_width,$new_height,$rate=100);
2、方案2
$res = cutPhoto($old_src,$new_src,$new_width,$new_height,$rate=100);
四、nginx裁图模块
1、使用程序来裁图,会遇到几个问题:
1.1 如果再增加一个缩略图尺寸,则需要对原来的所有图片重新处理一次,很麻烦
1.2 压缩图片,会使用户上传处理速度变慢
1.3 需要存储非常多份的缩略图
2、nginx有个扩展,阿里开源的,可以实现上面程序中的两种切图效果
2.1 找运维同事帮忙部署
2.2 nginx切图,访问缩略图的时候,nginx会看,是否已经有裁减过该尺寸的图片,如果有,直接访问,没有则裁减并缓存
2.3 配置的时候,缩略图规则写到最后
比如原图访问 http://***/***/a.jpg
则缩略图规则为 http://***/***/a.jpg_600x400
php压缩图片函数
/*
*编 写:袁 亮
*时 间:2013-02-27
*功 能:常见的两种缩略图生成策略实现,图片不允许变形,在生成缩略图之前需要确保图片存放目录存在并有写权限
可以调用createDirs创建目录并赋予相应的权限,该函数支持多级目录
在window下测试时处理大图片可能会出现内存不足,可以使用ini_set('memory_limit', '12M');更改内存限制
*/
function createDirs($dir,$model=0777){//创建多级目录
return is_dir($dir) or createDirs(dirname($dir),$model) and mkdir($dir,$model);
}
/*
*生成一张给定宽高的缩略图,超出部分进行居中截图,只支持jpg,gif,png格式,生成的是jpg格式图片
@old_src:源图地址
@new_src:缩略图地址
@new_width:缩略图宽
@new_height:缩略图高
@rate:图片质量,0-100,可选参数,默认100
#返回值:1:缩略图生成成功,-1:不支持该图片类型,-2:图片文件错误,-3:缩略图生成失败
*/
function cutPhotoDesign($old_src,$new_src,$new_width,$new_height,$rate=100){
$old_info = getimagesize($old_src);
switch($old_info[2]){
case 1:$im = imagecreatefromgif($old_src);break;
case 2:$im = imagecreatefromjpeg($old_src);break;
case 3:$im = imagecreatefrompng($old_src);break;
default:return -1;
}
if(!$im){
return -2;
}
$old_width = imagesx($im);
$old_height = imagesy($im);
if($old_width<=$new_width && $old_height<=$new_height){//图片过小,直接原图显示
$res = copy($old_src,$new_src);
imagedestroy($im);
return $res?1:-3;
}
$x_rate = $old_width/$new_width;//计算压缩图片尺寸,以及截图开始位置
$y_rate = $old_height/$new_height;
if($x_rate<$y_rate){//宽度优先压缩
$dst_x = $new_width;
$dst_y = ceil($old_height/$x_rate);
$new_start_x = 0;
$new_start_y = ($dst_y-$new_height)/2;
}else{//高度优先压缩
$dst_x = ceil($old_width/$y_rate);
$dst_y = $new_height;
$new_start_x = ($dst_x-$new_width)/2;
$new_start_y = 0;
}
$newim = imagecreatetruecolor($dst_x,$dst_y);//等比例压缩图片,将图片的宽或者高压缩到指定参数
imagecopyresampled($newim,$im,0,0,0,0,$dst_x,$dst_y,$old_width,$old_height);
$cutim = imagecreatetruecolor($new_width,$new_height);//将宽高都固定成指定参数,超出的部分居中截图
imagecopyresampled($cutim,$newim,0,0,$new_start_x,$new_start_y,$new_width,$new_height,$new_width,$new_height);
$res = imagejpeg($cutim,$new_src,$rate);//对图像进行截图
imagedestroy($im);
imagedestroy($newim);
imagedestroy($cutim);
return $res?1:-3;
}
/*
*生成一张宽高不超过给定参数的缩略图,只支持jpg,gif,png格式,生成的是jpg格式图片
@old_src:源图地址
@new_src:缩略图地址
@new_width:缩略图宽
@new_height:缩略图高
@rate:图片质量,0-100,可选参数,默认100
#返回值:1:缩略图生成成功,-1:不支持该图片类型,-2:图片文件错误,-3:缩略图生成失败
*/
function cutPhoto($old_src,$new_src,$new_width,$new_height,$rate=100){
$old_info = getimagesize($old_src);
switch($old_info[2]){
case 1:$im = imagecreatefromgif($old_src);break;
case 2:$im = imagecreatefromjpeg($old_src);break;
case 3:$im = imagecreatefrompng($old_src);break;
default:return -1;
}
if(!$im){
return -2;
}
$old_width = imagesx($im);
$old_height = imagesy($im);
if($old_width<=$new_width && $old_height<=$new_height){//图片过小,直接原图显示
$res = copy($old_src,$new_src);
imagedestroy($im);
return $res?1:-3;
}
$x_rate = $old_width/$new_width;//计算缩略图实际尺寸
$y_rate = $old_height/$new_height;
if($x_rate<$y_rate){
$dst_x = ceil($old_width/$y_rate);
$dst_y = $new_height;
}else{
$dst_x = $new_width;
$dst_y = ceil($old_height/$x_rate);
}
$newim = imagecreatetruecolor($dst_x,$dst_y);//按实际大小生成一张画布
$bg = imagecolorallocate($newim,255,255,255);//白色背景
imagecopyresampled($newim,$im,0,0,0,0,$dst_x,$dst_y,$old_width,$old_height);//将图片内容复制到新画布中
$res = imagejpeg($newim,$new_src,$rate);//将画布中的内容写入文件
imagedestroy($im);
imagedestroy($newim);
return $res?1:-3;
}
php类初阶:简单使用
编 写:袁 亮
时 间:2015-07-13
说 明:php类初阶,简单使用
一、为什么需要使用类?
1、当项目比较复杂,代码量过大,我们会将两种代码给封装成函数:
1.1 一种是好多地方重复使用的
1.2 一种是逻辑比较复杂,不想跟其他代码混在一块
2、当项目更加庞大的时候,使用函数还是不能很好的组织代码,这个时候,我们会希望通过类来处理
比如对数据库,可能有10几种操作,每种操作都可以封装成一个函数,但是各个函数又都是针对的数据库做的处理
这个时候,我们会希望将对数据库的所有操作都封装成一个类,这个类里有各种各样的函数做不同的处理
这个类本身又有一些公共的变量,可以在这些函数内部使用
二、简单范例
//类定义
class Mysqls{
public $_dblink;//类中的公共变量
function __construct(){//构造方法,在类实例化时将自动执行
$this->_dblink = '';
}
//执行一条sql
function query($sql){
return mysql_query($sql,$this-_dblink);//使用类中的成员变量
}
//从数据库中获取一行数据
function getRow($sql){
$query = $this->query($sql);//调用类中的成员函数
//后续处理
}
//从数据库中获取多行数据
function getRows($sql){
}
}
$ms = new Mysqls;//实例化一个类,得到一个对象
$data = $ms->getRow($sql);//调用对象中的成员函数
var_dump($data);
die();
三、使用
1、命名规范请点此参考
类名、函数名、变量名
2、使用$this来调用成员函数和成员变量
3、成员变量,以_开头命名
四、目标:
1、能自己写一个简单的类,并使用
2、理解类、对象、实例化的差异
类:定义的一类特殊数据结构,一种抽象
对象:符合一类规则的某个具体数据
实例化:根据某个类,具体到一个对象的过程,交实例化
3、一个类,可以实例化多个对象,各个对象之间独立(静态变量例外,后期自己了解),可以自己写代码测试下
curl阶段三:模拟用户表单提交数据
编 写:袁 亮
时 间:2015-07-10
说 明:curl高阶应用,模拟用户表单提交数据
一、应用场景
1、伪装用户登录,爬取需要登录才能访问的数据
2、提交表单,进行一些操作,比如自动发帖等,刷刷投票什么的
3、内部接口调用,模拟提交数据,作为参数
二、get传送
没什么好说的,直接在链接后面拼起来就好了
三、post数据传送
1、form表单提交数据,编码设置,直接参考w3cschool
application/x-www-form-urlencoded 在发送前编码所有字符(默认)
multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
text/plain 空格转换为 "+" 加号,但不对特殊字符编码。
2、一般的表单项
2.1 采用的是第一编码方式
2.2 代码使用:
$data = array(
'title' => '大家好,我是新人,请多多关照',
'content' => '第一次来这边,发现好多东西好有帮助...',
);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//Post提交的数据包
3、文件上传
3.1 代码和上面一样
3.2 文件地址使用@符合加载绝对路径之前即可,先绝对路径,否则很容易出错
3.3 例如:
$data = array(
'title' => '大家好,我是新人,请多多关照',
'content' => '第一次来这边,发现好多东西好有帮助...',
'photo' => '@/opt/ci123/www/html/ciphot/demo.jpg',
);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//Post提交的数据包
3.4 还有个参数 CURLOPT_UPLOAD,没用过,有兴趣可以自己了解下
四、http basic验证
1、有些项目或者网站,访问的时候加了http basic验证,直接抓取会失败
2、知道账号密码的话,简单设置下即可
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "username:password");
五、错误信息显示
1、在exec执行之后,如果出错,可以返回报错信息方便查看
$img = curl_exec($ch);
$err = curl_error($ch);
if($err){
return $err;
}
2、很少用,一般是在上传图片的时候,图片路径出错会出这个问题
3、curl抓取不到,请注意是否能ping的通域名,能否正常访问那个文件,ping一下,或者wget下那个地址
4、ipv6报错提示:curl: (6) Couldn't resolve host(域名能正常访问的话),设置使用ipv4的
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4)
curl阶段二:伪造请求信息及其他小知识
编 写:袁 亮 时 间:2015-07-09 说 明:curl请求伪造信息及其他小知识点 一、为什么需要伪造? 在抓取的过程中,经常会出现被人屏蔽,不给抓了,这个时候,我们需要让自己尽量像是一个正常的用户去抓取相应数据 二、伪造哪些信息? 1、useragent 1.1 最初级的,所有浏览器、app都会带上自己的ua信息,如果没有,那就是直接告诉别人,我不是一个正常访问 1.2 curl_setopt($ci, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0'); 1.3 ua内容,可以使用firebug,查看网络中的请求头信息,复制下来即可,也可以准备多个,随机使用 2、referer 2.1 浏览器告知服务端,上一个请求的链接是什么;特别是在图片的抓取上,很多网站都会判断referer是不是自己的网站 2.2 根据网址,自动伪造首页referer $urlinfo = parse_url($url); $host = $urlinfo["scheme"].'://'.$urlinfo['host']; curl_setopt ($ch, CURLOPT_REFERER, $host); 3、cookie 3.1 很多网站需要登录才能显示内容,这个时候,就需要伪造相应的登陆cookie,否则抓取不到内容 3.2 主要两种办法:一个是在浏览器里登陆相应的账号,从firebug等,查看请求头里的cookie内容,复制下来 第二种是使用账号密码,在curl中,模拟登陆,然后将cookie存到txt文件里,下次将cookie带上去抓取数据 3.3 第一种比较快捷方便,特别是有验证码的网站,适合短时间抓取,但可能会因为cookie失效等原因出问题 第二种,如果有验证码会很麻烦,但是优点在于只要账号密码不出问题,程序就很少出问题 3.4 第一种代码: curl_setopt ($ch, CURLOPT_COOKIE, 'BAIDUID=7268C693B1F385AC297F677E90E092D4:FG=1;BIDUPSID=6093A44AECD856D0FFBD012FA16D99BA; PSTM=1436169100; BD_UPN=13314352;BDUSS=VRFdUMyRndUWmdkLUxrTW5-d0NjSVZocktDVHdublh1SFhqRTFHSlB3c2piTVJWQVFBQUFBJCQAAAAAAAAAAAEAAAD6lOAweXVhbmxpYW5nODQ3XzEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPfnFUj35xVd;BD_HOME=1;H_PS_PSSID=11194_1442_14601_16148_13245_16035_10813_14429_10211_12868_16167_14667_16210_14954_15397_11465_13932_13612;BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0;BD_CK_SAM=1;__bsi=15490895447769138228_00_3_R_N_25_0303_C02F_N_I_I_0'); 3.5 第二种 伪造登陆的请参考阶段三,form表单伪造,cookie保存和下次使用就下面两段代码,注意文件写权限问题 curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_file); //连接结束后保存cookie信息的文件。 curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file); 4、使用代理访问 4.1 很多网站,都会对同一个ip的访问次数和频率做限制,这个时候可以使用代理来隐藏我们的ip 4.2 代理有很多种,具体的参考其他文档,网上找的免费代理经常失效,不稳定,所以保持代理库的及时更新非常重要 4.3 使用方法 curl_setopt($curl, CURLOPT_PROXY, '代理ip:代理端口'); 5、伪造ip 5.1 将自己作为代理的一层,伪造header中的x-forwared-for来达到 5.2 关于ip的相关知识,可以搜索查看其他文档 5.3 采用的伪造头信息来达到目标,上面的那些伪造也可以使用这个方法达成,只要对http头熟悉即可 $header = array( 'X-FORWARDED-FOR:202.103.229.40', '...'//其他需要伪造的,再加一行即可 ); curl_setopt ($ch, CURLOPT_HTTPHEADER , $header ); //构造IP 三、curl超时 1、所有curl请求,必须设置超时时间,否则很容易导致进场堆积,将服务器拖垮 2、超时有两个,一个是连接超时,一个是传输内容超时,都必须要设置 3、设置代码: curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT , 2 );//连接时间 curl_setopt ($ch, CURLOPT_TIMEOUT , 3 );//最长执行时间 四、跟踪链接跳转 1、抓取的时候,会出现目标被header跳转 2、跳转的代码在header中获取 curl_setopt($ch,CURLOPT_HEADER,true);//将头信息输出,默认只输出http的body部分(非html的body) curl_setopt($ch,CURLOPT_NOBODY,true);//不输出body数据,如果确定有location跳转的话用,一般情况下不要设置 3、设置代码: curl_setopt ($ch, CURLOPT_FOLLOWLOCATION , true );//跟随跳转 curl_setopt ($ch, CURLOPT_MAXREDIRS , 2 );//跳转次数限制,防止死循环等