就像网上有些快递查询系统一样,在本地显示EMS验证码的图片,在表单中输入单号和验证码 向EMS服务器进行模拟浏览器的查询,并取得查询结果。这个功能我用CURL已经实现了。 但是我现在用的空间服务器不支持CURL,只能用其他的办法实现了。就选择了snoopy类,这个在我的空间是能用的。EMS的查询验证机制是这样的:
一 在表单页 生成随机码,验证码的表单输入框的名称也是随机变化
二 验证码和SESSIONID
表单页:http://www.ems.com.cn/qcgzOutQueryAction.do?reqCode=gotoSearch
处理页:http://www.ems.com.cn/qcgzOutQueryAction.do
验证码:http://www.ems.com.cn/servlet/ImageCaptchaServlet模拟查询流程
1 连接表单页 取得随机码 验证码表单名称 和 JSESSIONID
2 带着这个JSESSIONID连接验证码页,显示炎症码
3 带着JSESSIONID和提交数据模拟POST处理页,取得返回结果。共三个文件 ems.php emscode.php emspost.php<?PHP
//ems.php
session_start();
include("Snoopy.class.php");
$url = "http://www.ems.com.cn/qcgzOutQueryAction.do?reqCode=gotoSearch";
$url2 = "http://www.ems.com.cn/qcgzOutQueryAction.do";
$snoopy = new Snoopy;
$snoopy->fetch($url); //获取所有内容
//print_r($snoopy->headers);
$c =$snoopy->headers[5];
preg_match_all('|Set-Cookie: (.*);|U', $c, $mycookie);
$_SESSION['sid'] = $mycookie[1][0];$content = $snoopy->results;
preg_match('/name="myEmsbarCode" value="(.*)"/i',$content,$myEmsbarCode);
preg_match('/<input name="(.*)" type="text" maxlength="5"/i',$content,$imgname);
$myEmsbarCode =$myEmsbarCode[1];
$imgname = $imgname[1];
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>中国邮政集团公司-全程跟踪查询</title>
<script>
<!--
function checkdata(v){
if(v){
var dzzmailnum = this.document.form1.DzzmailNum.value;
if(''==dzzmailnum){
alert("请输入查询单证照号!");
form1.DzzmailNum.focus();
return false;
}else{
trackagainform.style.display = "none";
progress.style.display = "";
return true;
}
}
var bool;
var str;
var len;
var i;
var charsets;
bool="true";
charnum="0123456789";
charsets="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
str=this.document.form1.mailNum.value;
len=str.length;
if (str=="") {
bool="false1";
}
else{
if (len!=13) {
bool="false2";
}
else {
if ((charsets.indexOf(str.substring(0,1))==-1)||(charsets.indexOf(str.substring(1,2))==-1)) {bool="false3";}
for(i=2;i<11;i++) {
//alert(charnum.indexOf(ch,0));
if (charnum.indexOf(str.substring(i,i+1),0)<0) {bool="false4";}
}
if ((charsets.indexOf(str.substring(11,12))==-1)||(charsets.indexOf(str.substring(12,13))==-1)) {bool="false5";}
// if(4!=document.form1.checknumone.value.length) {bool="false6";}
}
}
if (bool!="true") {
if (bool=="false1") {alert("用户查询的输入值不能为空!");bool="true";return false;}
if (bool=="false2") {alert("输入值必须为13位!");bool="true";return false;}
if (bool=="false3") {alert("输入值前两位必须为字符!");bool="true";return false;}
if (bool=="false4") {alert("输入值第3位至第11位必须为数字123456789!");bool="true";return false;}
if (bool=="false5") {alert("输入值后两位必须为字符!");bool="true";return false;}
// if (bool=="false6") {alert("请输入4位查询验证码!");return false;}
}
else {
form1.submit();
}
}
-->
</script>
</head>
<body>
<form name="form1" method="post" action="emspost.php" onSubmit="return checkdata(false);">
<table border="1" cellpadding="0" cellspacing="0" width="300" align="center">
<tr>
<td height=25 colspan="2" align="center"><b>EMS运单查询系统</b></td>
</tr>
<tr>
<td width="90" height=25 align="right">运单号:</td>
<td colspan="2">
<input type="text" name="mailNum" value="EE082209212CS"/>
<input type="hidden" name="reqCode" value="browseBASE"/>
<input type="hidden" name="myEmsbarCode" value="<?php echo $myEmsbarCode ?>"/>
</td>
</tr>
<tr>
<td width="90" height=25 align="right">验证码:</td>
<td align="left">
<img align="absmiddle" src="emscode.php" style="cursor:pointer;" onClick="this.src='emscode.php';" />
<input type="text" name="verifycode" size="5" />
<INPUT type="hidden" name="imgname" value="<?php echo $imgname; ?>" />
</td>
</tr>
<tr>
<td align="center" colspan="2"><input type="submit" name="Submit2" value=" 查 询 ">
</td>
</tr>
</table>
</form>
</body>
</html>
第二个取验证码的emscode.php<?PHP
session_start();
$url = "http://www.ems.com.cn/servlet/ImageCaptchaServlet"; include("Snoopy.class.php");
$snoopy = new Snoopy;
$snoopy->agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)"; //伪装浏览器
$snoopy->referer = "http://www.ems.com.cn"; //伪装来源页地址 http_referer
$snoopy->rawheaders["COOKIE"]=$_SESSION['sid']; //伪装sessionid
$snoopy->rawheaders["Pragma"] = "no-cache"; //cache 的http头信息
$snoopy->rawheaders["X_FORWARDED_FOR"] = "211.156.193.130"; //伪装ip
$snoopy->fetch($url); //模拟浏览器连接并取得返回结果
echo($snoopy->results);?>第三部分emspost.php<?php
//提交数据
session_start();
$sid = $_SESSION['sid'];
$url = "http://www.ems.com.cn/qcgzOutQueryAction.do?reqCode=gotoSearch"; //填写信息页
$url2 = "http://www.ems.com.cn/qcgzOutQueryAction.do"; //提交判断页
$posts = array();
$posts['reqCode'] = 'browseBASE';
$posts['myEmsbarCode'] = $_POST["myEmsbarCode"];
$posts['mailNum'] = $_POST["mailNum"];
$posts[$_POST["imgname"]] = $_POST["verifycode"];
include("Snoopy.class.php");
$snoopy = new Snoopy;
$snoopy->agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)"; //伪装浏览器
$snoopy->referer = $url; //伪装来源页地址 http_referer
$snoopy->rawheaders["COOKIE"]=$_SESSION['sid']; //伪装sessionid
$snoopy->rawheaders["Pragma"] = "no-cache"; //cache 的http头信息
$snoopy->rawheaders["X_FORWARDED_FOR"] = "211.156.193.130"; //伪装ip
$snoopy->submit($url2,$posts); //模拟浏览器提交并取得返回结果
print_r($snoopy->results);
?>
为什么每次查询的结果都是“停留页面时间过长”、“校验查询标准失败,请重新输入”等等。 请高说作答。
一 在表单页 生成随机码,验证码的表单输入框的名称也是随机变化
二 验证码和SESSIONID
表单页:http://www.ems.com.cn/qcgzOutQueryAction.do?reqCode=gotoSearch
处理页:http://www.ems.com.cn/qcgzOutQueryAction.do
验证码:http://www.ems.com.cn/servlet/ImageCaptchaServlet模拟查询流程
1 连接表单页 取得随机码 验证码表单名称 和 JSESSIONID
2 带着这个JSESSIONID连接验证码页,显示炎症码
3 带着JSESSIONID和提交数据模拟POST处理页,取得返回结果。共三个文件 ems.php emscode.php emspost.php<?PHP
//ems.php
session_start();
include("Snoopy.class.php");
$url = "http://www.ems.com.cn/qcgzOutQueryAction.do?reqCode=gotoSearch";
$url2 = "http://www.ems.com.cn/qcgzOutQueryAction.do";
$snoopy = new Snoopy;
$snoopy->fetch($url); //获取所有内容
//print_r($snoopy->headers);
$c =$snoopy->headers[5];
preg_match_all('|Set-Cookie: (.*);|U', $c, $mycookie);
$_SESSION['sid'] = $mycookie[1][0];$content = $snoopy->results;
preg_match('/name="myEmsbarCode" value="(.*)"/i',$content,$myEmsbarCode);
preg_match('/<input name="(.*)" type="text" maxlength="5"/i',$content,$imgname);
$myEmsbarCode =$myEmsbarCode[1];
$imgname = $imgname[1];
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>中国邮政集团公司-全程跟踪查询</title>
<script>
<!--
function checkdata(v){
if(v){
var dzzmailnum = this.document.form1.DzzmailNum.value;
if(''==dzzmailnum){
alert("请输入查询单证照号!");
form1.DzzmailNum.focus();
return false;
}else{
trackagainform.style.display = "none";
progress.style.display = "";
return true;
}
}
var bool;
var str;
var len;
var i;
var charsets;
bool="true";
charnum="0123456789";
charsets="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
str=this.document.form1.mailNum.value;
len=str.length;
if (str=="") {
bool="false1";
}
else{
if (len!=13) {
bool="false2";
}
else {
if ((charsets.indexOf(str.substring(0,1))==-1)||(charsets.indexOf(str.substring(1,2))==-1)) {bool="false3";}
for(i=2;i<11;i++) {
//alert(charnum.indexOf(ch,0));
if (charnum.indexOf(str.substring(i,i+1),0)<0) {bool="false4";}
}
if ((charsets.indexOf(str.substring(11,12))==-1)||(charsets.indexOf(str.substring(12,13))==-1)) {bool="false5";}
// if(4!=document.form1.checknumone.value.length) {bool="false6";}
}
}
if (bool!="true") {
if (bool=="false1") {alert("用户查询的输入值不能为空!");bool="true";return false;}
if (bool=="false2") {alert("输入值必须为13位!");bool="true";return false;}
if (bool=="false3") {alert("输入值前两位必须为字符!");bool="true";return false;}
if (bool=="false4") {alert("输入值第3位至第11位必须为数字123456789!");bool="true";return false;}
if (bool=="false5") {alert("输入值后两位必须为字符!");bool="true";return false;}
// if (bool=="false6") {alert("请输入4位查询验证码!");return false;}
}
else {
form1.submit();
}
}
-->
</script>
</head>
<body>
<form name="form1" method="post" action="emspost.php" onSubmit="return checkdata(false);">
<table border="1" cellpadding="0" cellspacing="0" width="300" align="center">
<tr>
<td height=25 colspan="2" align="center"><b>EMS运单查询系统</b></td>
</tr>
<tr>
<td width="90" height=25 align="right">运单号:</td>
<td colspan="2">
<input type="text" name="mailNum" value="EE082209212CS"/>
<input type="hidden" name="reqCode" value="browseBASE"/>
<input type="hidden" name="myEmsbarCode" value="<?php echo $myEmsbarCode ?>"/>
</td>
</tr>
<tr>
<td width="90" height=25 align="right">验证码:</td>
<td align="left">
<img align="absmiddle" src="emscode.php" style="cursor:pointer;" onClick="this.src='emscode.php';" />
<input type="text" name="verifycode" size="5" />
<INPUT type="hidden" name="imgname" value="<?php echo $imgname; ?>" />
</td>
</tr>
<tr>
<td align="center" colspan="2"><input type="submit" name="Submit2" value=" 查 询 ">
</td>
</tr>
</table>
</form>
</body>
</html>
第二个取验证码的emscode.php<?PHP
session_start();
$url = "http://www.ems.com.cn/servlet/ImageCaptchaServlet"; include("Snoopy.class.php");
$snoopy = new Snoopy;
$snoopy->agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)"; //伪装浏览器
$snoopy->referer = "http://www.ems.com.cn"; //伪装来源页地址 http_referer
$snoopy->rawheaders["COOKIE"]=$_SESSION['sid']; //伪装sessionid
$snoopy->rawheaders["Pragma"] = "no-cache"; //cache 的http头信息
$snoopy->rawheaders["X_FORWARDED_FOR"] = "211.156.193.130"; //伪装ip
$snoopy->fetch($url); //模拟浏览器连接并取得返回结果
echo($snoopy->results);?>第三部分emspost.php<?php
//提交数据
session_start();
$sid = $_SESSION['sid'];
$url = "http://www.ems.com.cn/qcgzOutQueryAction.do?reqCode=gotoSearch"; //填写信息页
$url2 = "http://www.ems.com.cn/qcgzOutQueryAction.do"; //提交判断页
$posts = array();
$posts['reqCode'] = 'browseBASE';
$posts['myEmsbarCode'] = $_POST["myEmsbarCode"];
$posts['mailNum'] = $_POST["mailNum"];
$posts[$_POST["imgname"]] = $_POST["verifycode"];
include("Snoopy.class.php");
$snoopy = new Snoopy;
$snoopy->agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)"; //伪装浏览器
$snoopy->referer = $url; //伪装来源页地址 http_referer
$snoopy->rawheaders["COOKIE"]=$_SESSION['sid']; //伪装sessionid
$snoopy->rawheaders["Pragma"] = "no-cache"; //cache 的http头信息
$snoopy->rawheaders["X_FORWARDED_FOR"] = "211.156.193.130"; //伪装ip
$snoopy->submit($url2,$posts); //模拟浏览器提交并取得返回结果
print_r($snoopy->results);
?>
为什么每次查询的结果都是“停留页面时间过长”、“校验查询标准失败,请重新输入”等等。 请高说作答。
1,先找个录包工具,在 EMS.COM.CN 上操作几次,然后分析其发包和收到的HTTP包。
2,仔细耐心地分析。
3,动手写代码,一般用 SOCKETOPEN 之类的可以控制超时的函数来操作,否则很容易引起雪崩,导致你自己的网站都很慢。
1 连接表单页,取得相应的随机码同时也取的cookie
2 连接验证码页,并且把刚才取得的cookie也发送过去(使得服务器不在产生新的sessionid,这一点也确实做到了,在分析验证码的header时,确实已经不再返回新的sessionid了)
3 把表单所需要的值和sessionid一起发送给验证页,并取得返回值。(这一部分返回的header也分析了,也没有JSESSIONID,可见服务器是认可发给他的sessionid的)我在用curl实现的时候很轻松的获取正确的返回结果,可是用snoopy却总是返回“停留页面时间过长”、“校验查询标准失败,请重新输入”等等curl的流程和snoopy的是一样的,只是在存储cookie上略有区别,curl是标准的网景的cookie格式;snoopy是取得header中的JSESSIONID并存入session['sid']中,在页面中传递。我观察两个方法虽不同,但取得的JSESSIONID是一样的。
我用抓包工具仔细分析过。
JSESSIONID和表单页的随机码是一一对应的,所以在取的验证码页的时候不能让他产生新的JSESSIONID,否则先前取得的随机码和JSESSIONID就对不上号了,验证就会失败。
首先感谢你的回复。在取验证码的时候 不能让他产生新的SESSIONID,否则先前的表单页获取的随机码就失效了。
我在用curl的时候也是这么做的。原理都一样。因为我对snoopy也不是多熟悉,所以不理解我的代码为何最后取不到正确的答案呢
我以前做过类似东西,有过操作,不论变不变,我都重新取值,完全模拟当然这里不需要
另外,把你后面两文件的伪造ip全部去掉,我测试成功了
结贴给分
在emscode和emspost页,必须要带着catch里的sessionid来post值的,怎么能no-catch呢呵呵,当初就没看到这里。
信息提示:页面停留时间过长导致邮件查询标志丢失,请刷新查询页面。
好吧 ,我把我的源码公开下载。演示地址:http://life169.web-141.com/ems/ems.php下载地址:http://download.csdn.net/source/2570680
include("Snoopy.class.php");
$url = "http://www.ems.com.cn/qcgzOutQueryNewAction.do?reqCode=gotoSearch";
$url2 = "http://www.ems.com.cn/qcgzOutQueryNewAction.do"; $snoopy = new Snoopy;
$snoopy->fetch($url); //获取所有内容
print_r($snoopy->headers);打印头信息,返回的是:
Array ( [0] => HTTP/1.1 200 OK [1] => Content-Type: text/html; charset=GB2312 [2] => X-Powered-By: Servlet/2.4 JSP/2.0 [3] => Accept-Ranges: bytes [4] => Connection: close [5] => Date: Tue, 15 Mar 2011 11:24:53 GMT [6] => Age: 1876 [7] => Content-Length: 22804 ) 正确的返回信息应当是:
Array ( [0] => HTTP/1.1 200 OK [1] => Cache-Control: no-cache="set-cookie" [2] => Connection: close [3] => Date: Fri, 11 Mar 2011 07:42:04 GMT [4] => Content-Type: text/html; charset=GB2312 [5] => Set-Cookie: JSESSIONID=N5SMs1dMW1Wy8LJ48Z1ZhP1p2kS1GSgY5twTNxcYpz1MvgYZk0LQ!195316506; path=/ [6] => X-Powered-By: Servlet/2.4 JSP/2.0 ) 前面返回的里面没有JSESSIONID, 导致在后面的查询中返回不了查询结果, 我已经整了2天了,在网上查了大量资料,还是没有头绪,现在有一个奇怪现象,如果在浏览器打开ems.php页面,过一段时间再刷新页面后,又会返回正确的headers信息,但是过一阵又不能正确返回,为什么会出现这种情况, 希望有大虾能帮我看看是怎么回事? 急
我这个也是,有时候能取得到cookie信息,有什么时候取不到。高手帮忙解决啊!!!!