snoopy.php是一个php类,用来模仿web浏览器的功能,它能完成获取网页内容和发送表单的任务。
最新版本是1.2.4,发布日期是2011-06-15,主页地址是http://snoopy.sourceforge.net/,托管于sourceforge,但是sourceforge一直被墙,要cross。
要使用snoopy,只要下载到一个snoopy.php的单类文件引用就行了。
下面是它的一些特征:
1、方便抓取网页的内容
2、方便抓取网页的文字(去掉HTML代码)
3、方便抓取网页的链接
4、支持代理主机
5、支持基本的用户/密码认证模式
6、支持自定义用户agent,referer,cookies和header内容
7、支持浏览器转向,并能控制转向深度
8、能把网页中的链接扩展成高质量的url(默认)
9、方便提交数据并且获取返回值
10、支持跟踪HTML框架(v0.92增加)
11、支持再转向的时候传递cookies
我们通常使用在对网页或网站采集、分析、模拟提交表单等领域,下面是使用教程
以对php302.com这个站进行操作为例
test.php
<?php
include_once 'snoopy.php';
$s = new Snoopy();
$url = 'http://www.php302.com';
//开头
//获取网页内容
$s->fetch($URI);
echo $s->results;//网页html,这样写法直接就是把原版网页显示出来
$s->fetchtext($URI);
echo $s->results;//网页文本,去除所有dom
$s->fetchlinks($URI);
var_dump($s->results);//获取所有链接
result:
0 => string 'http://www.php302.com/' (length=22)
1 => string 'http://www.php302.com/' (length=22)
2 => string 'http://www.php302.com/tag/top10' (length=31)
3 => string 'http://www.php302.com/rss.xml' (length=29)
4 => string 'http://www.php302.com/?page=2' (length=29)
5 => string 'http://www.php302.com/?page=18' (length=30)
…………
$s->fetchform($URI);
var_dump($s->results);//获取所有表单
result:
0 =>
string
'<form action="" method="post" id="paginationForm1" style="display:inline">
<input size="1" value="1" type="text" name="paginationPage" />
</form>
<form action="" method="post" id="paginationForm2" style="display:inline">
<select id="paginationSelect" name="paginationLength">
<option value="5">5'... (length=1356)
//提交表单数据并且获取返回值
$URL = 'http://www.php302.com/search';//表单数据提交地址
$data = array('search_k'=>'php');//表单数据
$s->submit($URI,$data);
echo $s->result;//返回的html,直接把原版结果网页显示出来,表单数据数组的键值就是对应的name
$data = array('search_k'=>'php');
$files = array('pic'=>'./example.jpg);
$s->submit($URI,$data);
echo $s->result;//同上,但是同时模拟表单文件提交,文件数组的键值就是你要提交的文件的name
$s->submittext($URI,$data);
echo $s->results;//返回的网页的文本,去除所有dom
$s->submitlinks($URI,$data);
var_dump($s->results);//获取所有返回的链接
大家都知道,访问网页或者表单提交,同时要传输http header信息和cookie的,snoopy的强大之处就在于,他可以重定义header和cookie然后再进行提交,这样就完全可以模仿一个浏览器了!
//header&cookie重定义
include_once 'snoopy.php';
$s = new Snoopy();
$URI = 'http://www.php302.com';
你当前使用的是firefox,你想要返回ie的结果
$s->agent = "(compatible; MSIE 4.01; MSN 2.5; AOL 4.0; Windows 98)"; //伪装浏览器
有些网站会判断来源网页地址,比如表单提交,会判断必须来自于站内,防止的就是模拟提交,那么
$s->referer = "http://www.php302.com"; //伪装来源页地址 http_referer
不要返回缓存信息
$s->rawheaders["Pragma"] = "no-cache"; //不要cache
甚至伪装成代理ip
$s->rawheaders["X_FORWARDED_FOR"] = "127.0.0.101"; //伪装ip
$snoopy->submit(表单提交地址,提交数据数组);
设置cookie
$s->cookies["PHPSESSID"] = 'fc106b1918bd522cc863f36890e6fff7'; //伪装sessionid
必须说明的是,snoopy伪装的ip只是代理http头信息,和通过REMOTE_ADDR获取的ip无关,如果对方通过REMOTE_ADDR获取,这个伪装就无效,但是如果通过X_FORWARDED_FOR获取,就ok。
说到代理,snoopy可以直接通过代理服务器访问和提交,这样就无需伪装ip拉,对方获取的就是你是用的代理服务器ip
$s>proxy_host = "www.php302.com";//代理地址
$s->proxy_port = "8080"; //使用代理
$s->proxy_user = "username"; //代理用户名
$s->proxy_pass = "password"; //密码
还有一些有用的选项
$s->maxredirs = 2; //重定向次数,防止网页无限重定向,比如一些垃圾广告网站,那就影响抓取时间了
$s->expandlinks = true; //是否补全链接 在采集的时候经常用到
// 例如链接为 /images/taoav.gif 可改为它的全链接 http://www.taoav.com/images/taoav.gif,这个地方其实可以在最后输出的时候用preg_replace函数自己替换,但用snoopy本身选项更快捷
$s->maxframes = 5 //允许的最大框架数,针对可能出现的框架套框架再套框架再……
$s->timed_out = 100//超时时间,如果网站难访问的话,不要浪费脚本执行时间
$s->maxlength = 50000//返回的数据的字节数上限
另外,进行访问或者提交之后可以读取的额外信息有
$s->cookies //数组,字面意思,你从服务器得到的cookie
$s->response_code //http返回的状态码,可能返回404之类
$s->error //返回报错信息
下面来实际演示操作案例
登录php100.com:
凡是涉及到验证码的部分,通过snoopy都无法进行,需要额外的技术支持,而且即使到现在,也没有完全的破解验证码之法,验证的反验证的斗争近年一直在进行,这里就不扩散叙述了。
假设我们已经注册了一个php100的账号,现在可以通过snoopy进行自动登录
$URL = 'http://bbs.php100.com/login.php';//通过观察php100首页的登录框表单,得到提交地址和其他参数
要注意观察表单内的dom单元,所有有name属性的表单单元都要记录,包括有很多的隐藏单元即type为hidden的input元素
$data = array(
//'jumpurl'=>'http://www.php100.com/index.html',//隐藏参数之一,但是提交这个参数的话,就会出现405错误,尝试不提交这个参数,通过
'pwuser'=>'username',//用户名
'pwpwd'=>'password',//密码
'cktime'=>31536000,//隐藏参数之一
'step'=>2//隐藏参数之一
);
$s->referer = "http://www.php100.com";//为了保险起见,修改一下来源地址吧,又不花费什么
$s->submit($URL,$data);//提交
header('content-type:text/html;charset=gbk');//因为php100是gb2312编码的,所以输出结果之前定义一下编码,不然可能默认utf8,那文字就都乱码拉
echo $s->results;//结果如下图