中国联通采集实例
采集的目标站,中国联通http://shop.10010.com/number/searchNumber.action这个网站列表分页无变化,要解决分页问题,就要找到能够提供给我们分页信息的网址,这个地址栏的地址只是个障眼法了
列表分页无变化,可能是2种情况,一种是点分页直接post请求,更新整个页面的,这样的更新了整个页面,所以源代码我吗看到可能和服务器返回的数据相符,这样的直接在浏览器查看源码是真实的返回数据;
而另一种是ajax请求,是在不知不觉间页面的某些地方已经发生了变化,ajax请求只更新页面的一部分,理路只更新分页里德内容,这种请求的返回数据不能通过直接查看源码的方式,看返回的数据,因为ajax已经把返回的数据进行了处理了,真实的返回数据并不是你在浏览器查看源码说看到的,要看到这真实的返回数据,借助火车的模拟httppost提交工具才行
说明:这个网站分页就是ajax的,而内容页的请求时直接post的,好在这些网址都可以用get方式访问
通过抓包获得的数据,post数据中的每个参数代表的意识,通过下面的分析,可以得出各自的作用:这要仔细全面的分析源码,js文件,把该页面全部保存
这是全部的js文件,这个网站函数等都封装在了js文件,直接源码里看不到,通过js文件名字,可以大致了解各自的用途,下面在现有的地方就要找这些函数事件了
首先进入这个页面,要采集的3g和2g号码的区域,这个区域是最重要的,主要要分析这个区域,这个区域包含2个层,3g内容列表和2g内容列表层,而你在点击,这2个东西的时候,其实2个层时在互换的,也就是说3g和2g的层是重叠在一起的,点3g条,显示3g层,隐藏2g层;而它们都有个自的页脚部分,列表内容,就是说3g分页和2g是独立的,当你点击搜索,分页时只有的一种网络类型的数据的提交是有用的,而这个判断是3g网络还是2g网络,是由表单<form id="defaultnumber" name="defaultnumber" method="post" action="/number/searchNumber.action">里德一个表单项来判断,
首先把这个表单<form id="defaultnumber" name="defaultnumber" method="post" action="/number/searchNumber.action">
<input type="hidden" name="searchNumberInfo.order" id="order" value="0"/>
<input type="hidden" name="searchNumberInfo.order2g" id="order2g" value="0"/>
<input type="hidden" name="pageInfo.currPage" id="currPage" value="0" />
<input type="hidden" name="pageInfo.totalPager" id="totalPager" value="88"/>
<input type="hidden" name="formname" id="formname" value="defaultnumber" />
<input type="hidden" name="searchNumberInfo.currPage2g" id="currPage2g" value="0" />
<input type="hidden" name="searchNumberInfo.totalPager2g" id="totalPager2g" value="1011"/>
<input type="hidden" name="searchNumberInfo.oldnumberCardId" id="oldnumberCardId" value=""/>
<input type="hidden" name="searchNumberInfo.oldnumberCardId2g"id="oldnumberCardId2g"value=""/>
<input type="hidden" name="formname" id="formname2g" value="defaultnumber" />
<input type="hidden" name="searchNumberInfo.cardID" />
<input type="hidden" name="searchNumberInfo.isreserve" />
<input type="hidden" name="searchNumberInfo.saleCost" />
<input type="hidden" name="searchNumberInfo.numbercountryId" />
<input type="hidden" name="searchNumberInfo.numbercityId" />
<input type="hidden" name="searchNumberInfo.ruleID" />
<input type="hidden" name="searchNumberInfo.startCost" />
<input type="hidden" name="searchNumberInfo.onnetlong" />
<input type="hidden" name="searchNumberInfo.lowestcost" />
<input type="hidden" name="searchNumberInfo.nCardcost" />
<input type="hidden" name="searchNumberInfo.payType" />
<input type="hidden" id="selnetType" value=''/>
<input type="hidden" id="subprocessType" name="searchNumberInfo.processType" value="numbercard" />
<input type="hidden" name="searchNumberInfo.netType" id="netType" value='01'/>这些是这个表单的隐藏的项,这些项的意识可以通过一个个事件函数的执行过程,了解到它们的意识,所以当你触发了一个事件时,路点了搜索时这些项的值都可能已被重新设置,而你在源码中依然看不出这些改变,
下面是上面各个隐藏项的意识的是这样得出的:
1searchNumberInfo.netType项代表什么:当点击3g和2g互换的tab时,<div id="lab1" class="lab_pg_number_act" onclick="setTab(1)" style="width: 281px; margin-right: 1px;">3G号码</div>
<div id="lab2" class="lab_pg_number_nor" onclick="setTab(2)" style="width: 282px;">2G号码</div>可以知道触发了setTab函数,function setTab(lab) {
if (lab == 1) {
document.getElementById("lab1").className= "lab_pg_number_act";
document.getElementById("lab2").className= "lab_pg_number_nor";
$("#number3g").css("display","block");
$("#number2g").css("display","none");
$("#netType").val("01");
$("#selnetType").val("01");
// $("#nettypespan").html("3g");
// 显示首页左边3g套餐推荐
$(window.parent.document).find('#set_recommendation_div').show();
$(window.parent.document).find('#frame_2gpackage_div').hide();
} else {
document.getElementById("lab1").className= "lab_pg_number_nor";
document.getElementById("lab2").className= "lab_pg_number_act";
$("#number3g").css("display","none");
$("#number2g").css("display","block");
$("#netType").val("00");
$("#selnetType").val("00");
// $("#nettypespan").html("2g");
// 显示首页左边2g套餐推荐
$(window.parent.document).find('#set_recommendation_div').hide();
$(window.parent.document).find('#frame_2gpackage_div').show();
}
}通过这个函数可以知道,一方面实现了相互的切换,另一方面设置了 $("#netType").val("00");
$("#selnetType").val("00");id为netType和selnetType对象的值,而这2者正是上面表单里德隐藏项的searchNumberInfo.netType和<input type="hidden" id="selnetType" value=''/> ,表单提交时有name属性的才会被提交,当点击3g触发setTab(1),根据 if (lab == 1) 可知,点3gsearchNumberInfo.netType和selnetType的值被赋予01;相反点2gsetTab(2),可知被赋予了00,从而可知searchNumberInfo.netTyp表单项代表当前选择
的号码网络,01代表3g网络,00代表2g网络,这2个值在post时是3g和2g网络数据请求的标志,所以说当选择一种网络,post数据中的一些关于另一种网络的参数是可以去掉的
2 <input type="hidden" name="searchNumberInfo.order" id="order" value="0"/>项代表什么
往往它的名字就代表了它的意识,不知道的单词,用google翻译下,order是排序,可大至了解它的意识是对结果的排序,
,这需要看这2个切换的事件, <div id="sorttime"></div>
<div id="sortcost"></div>,这是2者的位置,它们在js文件里绑定了事件,注意这2个是3g层里的,所以这些设置的表单项是3g的,不是2g的,2g和3g的基本方法都是相同的,表单项名字带2g的就是关于2g的,而不带的就是3g的,以下都是以3g层里触发的事件做说明:
按时间排序被点击触发的函数:$('#sorttime').bind('click', function(){
$('#order').val("0");
$('#sorttime').addClass('sort_on'); $('#sorttime').html("按上架时间排序");
$('#sortcost').removeClass('sort_on').addClass('sort_out');$('#sortcost').html("按预存款排序");
gotopage3g();
});看到 $('#order').val("0");,id为order的对象就是表单的name="searchNumberInfo.order" id="order",可见searchNumberInfo.order=0带表按时间排序;
按预付款排序被点击触发的函数:$('#sortcost').bind('click', function(){
var order = $('#order').val();
if(order == '0' || order == '2'){
$('#order').val("1");
$('#sorttime').removeClass('sort_on').addClass('sort_out');$('#sorttime').html("按上架时间排序");
$('#sortcost').addClass('sort_on'); $('#sortcost').html("按预存款排序 ↓");
gotopage3g();
}else{
$('#order').val("2");
$('#sorttime').removeClass('sort_on').addClass('sort_out');$('#sorttime').html("按上架时间排序");
$('#sortcost').addClass('sort_on'); $('#sortcost').html("按预存款排序 ↑");
gotopage3g();
}
});,可知预付款时是1,2互换的,都可以,同时也发生了ajax请求gotopage3g()3.,这个函数在点击搜索按钮时会触发check():
3g搜索按钮源码<input type="button" class="btn" style="cursor: hand"
onclick="javascript:return check();" />
,function check(){
//自定义号码有输入值则检查是否数字
if((($("#cardID").val()!='号码自定义:如生日,纪念日等')&&($("#cardID").val()!='如生日,纪念日等')) && ($("#cardID").val()!='')){
if(/^\d+$/.test($("#cardID").val()) == false){
errDiv("自定义号码只能输入数字!");
return false;
}
}
//没输入值提交字定义号码为空值
if($("#cardID").val()=='号码自定义:如生日,纪念日等'||$("#cardID").val()=='如生日,纪念日等'){
$("#cardID").val("");
}
$("#currPage").val("0");
// document.defaultnumber.submit();
getNumberList(); // lizl
}
首先对自定义输入内容的检查,自定义号码只能输入数字,没输入值提交字定义号码为空值,$("#currPage").val("0");,就把表单pageInfo.currPage值设置0,也就是第一页,是从0开始的,然后触发getNumberList();,这个函数就是具体的ajax请求了,是核心函数
getNumberList函数:这个我略去了一部分代码/ ajax获取符合用户搜索条件的号码 lizl
var getNumberList = function(){
var netType = $("#netType").val(); // 网络类型 00:2g 01:3g
var urlStr = '/number/doGetNumberList.action';
var params = $("#defaultnumber").serialize();
if(netType=='00'){
$('#loadbox2g').show();
}else{
$('#loadbox').show();
}
$.ajax({
async:true,
type:'post',
url:urlStr,
cache: false ,
data:params,
timeout:5000,
dataType:'json',
success: function(data){
getNumberListCallBack(data, netType);
if(netType=="00"){
findPageButton2g(data.pager);
$('#loadbox2g').hide();
}else{
findPageButton(data.pager);
$('#loadbox').hide();
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {通过可以check()搜索和getNumberLis,可以知道点搜索发生了ajax请求,post方式,地址var urlStr = '/number/doGetNumberList.action';另外还有请求成功时的回调函数getNumberListCallBack(data, netType);,这个函数的作用就是处理服务器返回数据,处理后设置在3g层中,所以这是ajax与直接post的不同,重要的还是冲服务器返回的数据,里面一定有我们需要的东西,但ajax要用火车的模拟posthttp工具,来查看返回的数据,这样才能设置规则,获取内容页,有关这个工具的用法,论坛里有
再来看getNumberListCallBack函数,才能知道是潞河处理返回数据的,我用get提交可以返回和post提交相同的效果,这样可以请求是一个 文件,下载后用记事本打开看,返回的是一个对象,这个对象包含info和paper2个对象,info是一个数组,数组的每个成员又是一个包含号码信息的对象,info是包含内容的数据,paper是包含页面总页数等信息的,// 回调方法 lizl
function getNumberListCallBack(data, netType){
var list01 = "";
var list02 = "";
var list03 = "";
var infoList = data.info;
if(0 == infoList.length || null == infoList){
if(netType=="00"){
$("#2gnumberShow").empty().html("<tr><td colspan='6'>没有符合条件的号码</td></tr>");
}else{
$("#3gnumberShow").empty().html("<tr><td colspan='6'>没有符合条件的号码</td></tr>");
}
}else{
var table3gStr =
"<tbody>" +
"<tr>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 100px; height: 23px;'>号码</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 80px; height: 23px;'>预存款</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 100px; height: 23px;'>号码</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 83px; height: 23px;'>预存款</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 100px; height: 23px;'>号码</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 80px; height: 23px;'>预存款</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 20px;'> </td>" +
"</tr>" +
"<tr>" +
"<td colspan='6' height='5' style='height: 5px'>" +
"</td>" +
"</tr>" +
"</tbody>" +
"<tbody id='3gnumberShow'>" +
"<tr>" +
"<td colspan='2' style='border-right: 1px #CCCCCC solid;width: 180px' valign='top'>" +
"<table width='180px' border='0' cellspacing='0'id='3glist01' cellpadding='0' style='line-height: 190%;'>" +
"</table>" +
"</td>" +
"<td colspan='2' style='border-right: 1px #CCCCCC solid;width: 180px' valign='top'>" +
"<table width='180px' border='0' cellspacing='0'id='3glist02' cellpadding='0' style='line-height: 190%;'>" +
"</table>" +
"</td>" +
"<td colspan='2' style='width: 180px' valign='top'>" +
"<table width='180px' border='0' cellspacing='0'id='3glist03' cellpadding='0' style='line-height: 190%;'>" +
"</table>" +
"</td>" +
"</tr>" +
"</tbody>";
var table2gStr =
"<tbody>" +
"<tr>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 100px; height: 23px;'>号码</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 80px; height: 23px;'>预存款</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 100px; height: 23px;'>号码</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 83px; height: 23px;'>预存款</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 100px; height: 23px;'>号码</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 80px; height: 23px;'>预存款</td>" +
"<td style='border-bottom: 2px #999999 solid; font-weight: bold; width: 20px;'> </td>" +
"</tr>" +
"<tr>" +
"<td colspan='6' height='5' style='height: 5px'>" +
"</td>" +
"</tr>" +
"</tbody>" +
"<tbody id='2gnumberShow'>" +
"<tr>" +
"<td colspan='2' style='border-right: 1px #CCCCCC solid;width: 180px' valign='top'>" +
"<table width='180px' border='0' cellspacing='0'id='2glist01' cellpadding='0' style='line-height: 190%;'>" +
"</table>" +
"</td>" +
"<td colspan='2' style='border-right: 1px #CCCCCC solid;width: 180px' valign='top'>" +
"<table width='180px' border='0' cellspacing='0'id='2glist02' cellpadding='0' style='line-height: 190%;'>" +
"</table>" +
"</td>" +
"<td colspan='2' style='border-right: 1px #CCCCCC solid;width: 180px' valign='top'>" +
"<table width='180px' border='0' cellspacing='0'id='2glist03' cellpadding='0' style='line-height: 190%;'>" +
"</table>" +
"</td>" +
"</tr>" +
"</tbody>";
var cardID = "";
var isreserve = "";
var saleCost = "";
var numbercountryId = "";
var numbercityId = "";
var ruleID = "";
var startCost = "";
var onnetlong = "";
var lowestcost = "";
var nCardcost = "";
var payType = "";
for(var attr in infoList){
cardID = infoList.cardID;
isreserve = infoList.isreserve;
saleCost = infoList.saleCost;
numbercountryId = infoList.numbercountryId;
numbercityId = infoList.numbercityId;
ruleID = infoList.ruleID;
startCost = infoList.startCost;
onnetlong = infoList.onnetlong;
lowestcost = infoList.lowestcost;
nCardcost = infoList.nCardcost==undefined?"0":infoList.nCardcost;
payType = infoList.payType;
var numberMess =
"<tr style='cursor: pointer;' onmousemove=\"this.style.background='#FFE2AC'\""+
"onmouseout=\"this.style.background='#fff'\" onclick=\"defaultnumber[\'searchNumberInfo.cardID\'].value=\'"+cardID+"\'"+
";defaultnumber[\'searchNumberInfo.isreserve\'].value=\'"+isreserve+"\'"+
";defaultnumber[\'searchNumberInfo.saleCost\'].value=\'"+saleCost+"\'"+
";defaultnumber[\'searchNumberInfo.numbercountryId\'].value=\'"+numbercountryId+"\'"+
";defaultnumber[\'searchNumberInfo.numbercityId\'].value=\'"+numbercityId+"\'"+
";defaultnumber[\'searchNumberInfo.ruleID\'].value=\'"+ruleID+"\'"+
";defaultnumber[\'searchNumberInfo.startCost\'].value=\'"+startCost+"\'"+
";defaultnumber[\'searchNumberInfo.onnetlong\'].value=\'"+onnetlong+"\'"+
";defaultnumber[\'searchNumberInfo.lowestcost\'].value=\'"+lowestcost+"\'"+
";defaultnumber[\'searchNumberInfo.nCardcost\'].value=\'"+nCardcost+"\'"+
";defaultnumber[\'searchNumberInfo.payType\'].value=\'"+payType+"\'"+
";defaultnumber.action=\'searchOneNumber.action\'"+
";defaultnumber.submit();\">"+
" <td width='100px' style='text-align:right;'>"+
cardID+
" </td>"+
" <td width='80px' style='text-align:center;'>"+
startCost+
" 元</td>"+
"</tr>";
if(attr%3==0){
list01 += numberMess;
}
if(attr%3==1){
list02 += numberMess;
}
if(attr%3==2){
list03 += numberMess;
}
}
if(netType=="00"){
$('#numberList2g').empty().html(table2gStr);
$("#2glist01").empty();
$("#2glist02").empty();
$("#2glist03").empty();
$("#2glist01").html(list01);
$("#2glist02").html(list02==""?"<tr><td></td></tr>":list02);
$("#2glist03").html(list03==""?"<tr><td></td></tr>":list03);
}else{
$('#numberList').empty().html(table3gStr);
$("#3glist01").empty();
$("#3glist02").empty();
$("#3glist03").empty();
$("#3glist01").html(list01);
$("#3glist02").html(list02==""?"<tr><td></td></tr>":list02);
$("#3glist03").html(list03==""?"<tr><td></td></tr>":list03);
}
}
}这个函数执行后是,路过请求3g网络,则把格式化后的数据,设置在3g层,相反2g if(netType=="00"),则设置2g层,这都要看netType的值,所以说它很关键
这个函数里var numberMess =
"<tr style='cursor: pointer;' onmousemove=\"this.style.background='#FFE2AC'\""+
"onmouseout=\"this.style.background='#fff'\" onclick=\"defaultnumber[\'searchNumberInfo.cardID\'].value=\'"+cardID+"\'"+
";defaultnumber[\'searchNumberInfo.isreserve\'].value=\'"+isreserve+"\'"+
";defaultnumber[\'searchNumberInfo.saleCost\'].value=\'"+saleCost+"\'"+
";defaultnumber[\'searchNumberInfo.numbercountryId\'].value=\'"+numbercountryId+"\'"+
";defaultnumber[\'searchNumberInfo.numbercityId\'].value=\'"+numbercityId+"\'"+
";defaultnumber[\'searchNumberInfo.ruleID\'].value=\'"+ruleID+"\'"+
";defaultnumber[\'searchNumberInfo.startCost\'].value=\'"+startCost+"\'"+
";defaultnumber[\'searchNumberInfo.onnetlong\'].value=\'"+onnetlong+"\'"+
";defaultnumber[\'searchNumberInfo.lowestcost\'].value=\'"+lowestcost+"\'"+
";defaultnumber[\'searchNumberInfo.nCardcost\'].value=\'"+nCardcost+"\'"+
";defaultnumber[\'searchNumberInfo.payType\'].value=\'"+payType+"\'"+
";defaultnumber.action=\'searchOneNumber.action\'"+
";defaultnumber.submit();\">"+循环生成了格式化的代码,这个就是内容页提交时的模板,而这些项都是用ajax后返回的数据设置的,对应了上面表单的某些隐藏项,而当一个内容页被点击,发生的是表单的提交,首先用当前记录的设置对应的表单项的值,这次提交地址变了defaultnumber.action=\'searchOneNumber.action\'"根据名字就是说这个defaultnumber表单提交地址变成了单个号码请求的地址,这个地址是处理单个号码的,而这个地址也可以用get方式请求
还有就是点击分页时会发生什么:
4.gotopage3g()这是3g的输入框源码到第</td>
<td id="selectpageh" width="40px"><input id="inputpageh" type="text" style="color:#000000;text-align:center;" size="4" /></td>
<td>页</td>
<td><input type="button" value="确定" class='page_btnbg' onclick="gotopage3gh();"/></td>,点击触发了gotopage3gh(),//3g分页跳转到第几页
function gotopage3g(){
var inputpage=$("#inputpage").val();//输出的页数
var totalPager=$("#totalPager").val();//总页数
if(inputpage==""){
errDiv("请输入需要跳转的页数,当前满足条件的记录共有"+totalPager+"页。");
}else{
if(/^\d+$/.test(inputpage) == false){
$("#inputpage").val("");
$("#inputpageh").val(""); // lizl 2010-7-26
errDiv("请输入数字,当前满足条件的记录共有"+totalPager+"页。");
return false;
}
if(parseInt(inputpage)>parseInt(totalPager)){
errDiv("满足条件的号码只有"+totalPager+"页,请输入小于此数量的页数。");
$("#inputpage").val("");
$("#inputpageh").val(""); // lizl 2010-7-26
}else{
if(inputpage=="0"){
$("#currPage").val("0");
}else{
$("#currPage").val(parseInt(inputpage)-1);
}
getNumberList();
}
}
},getNumberList()前面已经说过了,检验输入是否和规范,然后是把输入的页码-1,做为currPage的值,然后ajax getNumberList(),可见页码和值差1,1 currPage=0,2currPage=1;
#inputpage#inputpageh 分别是3g下输入框对象,上输入框对象,带h就是上面的
还有个问题,就是页面的3g的页码部分是什么样的,在源码里找不到,这些也是在ajax后设置的success: function(data){
getNumberListCallBack(data, netType);
if(netType=="00"){
findPageButton2g(data.pager);
$('#loadbox2g').hide();
}else{
findPageButton(data.pager);
$('#loadbox').hide();
}
},findPageButton(data.pager);就是设置页码部分的,当然点的3g的,设置3g,2g不会被设置的,2者是独立的function findPageButton(pager){
var currPage = pager.currPage;
var totalPager = pager.totalPager;
var nowpage = totalPager == 0?0:currPage+1;
// $("#pager").pager({ pagenumber: currPage, pagecount: totalPager, buttonClickCallback: PageClick });
// $("#pagerh").pager({ pagenumber: currPage, pagecount: totalPager, buttonClickCallback: PageClick });
$("#pager").pager({ pagenumber: nowpage, pagecount: totalPager, buttonClickCallback: PageClick });
$("#pagerh").pager({ pagenumber: nowpage, pagecount: totalPager, buttonClickCallback: PageClick });
$('#totalnumpage').empty().html("共" + totalPager + "页 到第");
$('#totalnumpageh').empty().html(nowpage + "⁄" + totalPager + "页 到第");
$('#totalPager').val(totalPager);
$("#currPage").val(currPage);
$("#inputpage").val(currPage+1);
$("#inputpageh").val(currPage+1);
}data.pager是ajax返回的对象中的pager对象,具体可以把那个返回的文件打开,在最后就可以看到 $("#pager").pager({ pagenumber: currPage, pagecount: totalPager, buttonClickCallback: PageClick });等是设置上一页下一页按钮的 $('#totalPager').val(totalPager);可知表单<input type="hidden" name="pageInfo.totalPager" id="totalPager" value="88"/>,pageInfo.totalPager就是符合条件的3g的总页数, $("#currPage").val(currPage);当前页,页就是说它代表3g的页码,这个就代表重要的分页了,注意是3g的
还有就是用户可以选择的一些下拉框,之定义的,表单项了,还是3g的为例,靓号类型<select name="searchNumberInfo.searchRuleID"
id="ruleID" 预存款<select name="searchNumberInfo.numberStartCost"
id="startCost"号码自定义<input type="text" name="searchNumberInfo.numberCardId"
id="cardID" value="" size="15" maxlength="11"
路过想设置这些,对应源码里德值设置
到这里,基本已经结束了,内容页的请求前面也有说过了,可是还有一个重要的地方,那就是地区城市,好像在分页时没有表单项代表城市的<input type="hidden" name="searchNumberInfo.numbercountryId" />
<input type="hidden" name="searchNumberInfo.numbercityId" />,这2个是在请求内容页时被设置的,与列表分页无关,我试着设置了,不行
这就要分析当切换城市时发生的事件了,,切换城市,鼠标悬停在城市上,状态栏可以看到javascript:changeCity("002","002001")就是这个事件了
在left js文件里我找到这个函数,var changeCity = function (province, cityCode) {
clearCookie();
$.cookie("city", province + "|" + cityCode, {expires:200000, path:"/"});
var winurl = window.location.href;
if (index === 7 || index === 10 && endsWith(winurl, 'searchNumber.action')) {
toInfo(winurl);
} else {
window.location.reload();
}
};var endsWith = function(winurl, str){
if (winurl.indexOf(str) > 0) {
return true;
}
return false;
}肯定是返回true了,toInfo(winurl);应该执行了var toInfo = function(url)
{
var cityCode = $.cookie("city");
if (typeof cityCode === 'undefined' || cityCode === 'undefined|undefined' || cityCode === null || cityCode === '' || cityCode === '|') {
cityCode = '002|002001';
}
var area = cityCode.split('|');
var varform = window.document.createElement("form");
varform.name="infoform";
varform.action=url;
varform.method="post";
varform.style.display="none";
window.document.body.appendChild(varform);
var text1 = window.document.createElement("input");
text1.type="hidden";
text1.value=area;
text1.name="searchNumberInfo.cityno";
varform.appendChild(text1);
varform.submit();
}冲这个函数看出当切换城市时有个表单被提交了,发生post请求,不过这个表单是新建的,和上面的不是一个,只提交了searchNumberInfo.cityno参数,代表城市代码,所有城市代码在mydata js文件里,这里的城市名字是编码的,可以找个解码网站
这里有个 $.cookie("city");是从cookie里提取城市信息的,这里我只截取了被执行的部分,其他的看的不懂,总之else部分应该被执行了jQuery.cookie = function(name, value, options) {
else { // only name given, get cookie
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
};这个函数是遍历cooike的所有字段,当找到city字段时,截取出它的值,因为这个值是经过encodeURIComponent() 函数编码的,cookieValue = decodeURIComponent(cookie.substring(name.length + 1));,所以他用 decodeURIComponent解码,然后返回了cookieValue,
抓包获得的cooike:Cookie: WT_FPC=id=276c7ba14f71224a4cf1293353299905:lv=1293353960968:ss=1293353299905; city=002%7C002001; CheckCode=nylnL/oquq1wjqv2TA1vPIumIAocn40M; JSESSIONID=5tgJNXDCD2qSgh6xHKXmLnY4NP4pKcFfhCqhYJr3X182GdS9XGLR!887917931city=002%7C002001,解码后002|002001,%7C就是|,002是省份代码,002001是城市代码,这些都在mydata js文件里了
当你进入这个网站,它的默认城市是北京选号入网<script language="JavaScript" type="text/JavaScript">
var cityCode = $.cookie('city');
if (typeof cityCode == 'undefined' || cityCode == null || cityCode == '') {
document.write("[北京]");
}else{
var area = cityCode.split('|');
var cityName = cityData].cityName;
cityName="["+cityName+"]";
document.write(cityName);
}
</script>就是这段代码的效果,通过这些可以知道当你切换了城市的时候,由于changeCity("002","002001")里执行了clearCookie();function clearCookie() {
var expires = new Date();
expires.setDate(expires.getDate() - 1);
document.cookie = 'city=null;expires=' + expires.toGMTString();
} ,这个清理的以前的cooike,这个cooike过期了,包含新的城市的cooike被设置了
我发现了这个网站的搜索内容页等与cooike是有很大的关系,路过你切换了城市,那摩采集规则里采集到的就是该城市的号码;我试过用抓包获取不同城市时的cooike,目标站设置登录,可以采集同时采集不同的城市,还有时不行了,页不知道是地址太长,有换行,刚开始我把抓包的post数据连在提交地址后面,就是因为复制时有换行和空格,导致几种错误情况的发生
而服务器总是在判断当前用户浏览器选择的城市,路过这时请求地址不符合当前城市,会提示当前号码所在城市已转移;
3g列表页分页点击post数据:这里我点了3g的第10页,看到pageInfo.currPage=9了吧,就是3g的分页参数,注意这里的searchNumberInfo.netType=01了,为什么是01,因为是请求的3g号码searchNumberInfo.order=0&searchNumberInfo.order2g=0&pageInfo.currPage=9&pageInfo.totalPager=88&formname=defaultnumber&searchNumberInfo.currPage2g=0&searchNumberInfo.totalPager2g=1011&searchNumberInfo.oldnumberCardId=&searchNumberInfo.oldnumberCardId2g=&formname=defaultnumber&searchNumberInfo.cardID=&searchNumberInfo.isreserve=&searchNumberInfo.saleCost=&searchNumberInfo.numbercountryId=&searchNumberInfo.numbercityId=&searchNumberInfo.ruleID=&searchNumberInfo.startCost=&searchNumberInfo.onnetlong=&searchNumberInfo.lowestcost=&searchNumberInfo.nCardcost=&searchNumberInfo.payType=&searchNumberInfo.processType=numbercard&searchNumberInfo.netType=01&searchNumberInfo.searchRuleID=&searchNumberInfo.numberStartCost=&searchNumberInfo.numberCardId=%E5%A6%82%E7%94%9F%E6%97%A5%2C%E7%BA%AA%E5%BF%B5%E6%97%A5%E7%AD%89&searchNumberInfo.searchRuleID2g=&searchNumberInfo.numberStartCost2g=&searchNumberInfo.numberCardId2g=2g列表页分页点击post数据:这里我点了2g的第5页,看到searchNumberInfo.currPage2g=4了吧,就是2g的分页参数,注意这里的searchNumberInfo.netType=00了,为什么是00,因为是请求的2g号码,这样3g,2g是通过searchNumberInfo.netType判断的,那摩当选择3g请求,对应的2g的参数应该是可以不要的,这样数据就不那摩多了searchNumberInfo.order=0&searchNumberInfo.order2g=0&pageInfo.currPage=9&pageInfo.totalPager=90&formname=defaultnumber&searchNumberInfo.currPage2g=4&searchNumberInfo.totalPager2g=1011&searchNumberInfo.oldnumberCardId=&searchNumberInfo.oldnumberCardId2g=&formname=defaultnumber&searchNumberInfo.cardID=&searchNumberInfo.isreserve=&searchNumberInfo.saleCost=&searchNumberInfo.numbercountryId=&searchNumberInfo.numbercityId=&searchNumberInfo.ruleID=&searchNumberInfo.startCost=&searchNumberInfo.onnetlong=&searchNumberInfo.lowestcost=&searchNumberInfo.nCardcost=&searchNumberInfo.payType=&searchNumberInfo.processType=numbercard&searchNumberInfo.netType=00&searchNumberInfo.searchRuleID=&searchNumberInfo.numberStartCost=&searchNumberInfo.numberCardId=%E5%A6%82%E7%94%9F%E6%97%A5%2C%E7%BA%AA%E5%BF%B5%E6%97%A5%E7%AD%89&searchNumberInfo.searchRuleID2g=&searchNumberInfo.numberStartCost2g=&searchNumberInfo.numberCardId2g=这个是我用get连接提交地址主城的获取2g分页的列表网址:里面的参数我做了裁剪,把和3g有关的参数去掉了,测试也可行http://shop.10010.com/number/doGetNumberList.action?&searchNumberInfo.numbercityId=008010&searchNumberInfo.order2g=0&searchNumberInfo.currPage2g=【2g分页】&searchNumberInfo.netType=00&searchNumberInfo.searchRuleID2g=&searchNumberInfo.numberStartCost2g=&searchNumberInfo.numberCardId2g=内容页自定义网址格式:http://shop.10010.com/number/searchOneNumber.action?searchNumberInfo.cardID=[参数1]&searchNumberInfo.numbercityId=[参数2]&searchNumberInfo.netType=00,注意这3个参数都不可以少,而且要符合当前城市和网络类型
是2g的,当然searchNumberInfo.netType=00,改为01提示系统繁忙,就是错误,
当然内容页的post数据我也做了裁剪,我想定位一个号码,有网络类型,所属城市,和号码id就足够了,而提交了其他的路3g当前页,总页数,2g当前页,总页数,号码的价格等参数是没有必要的,测试可以
这个是我用get连接提交地址主城的获取3g分页的列表网址:里面的参数我做了裁剪,把和2g有关的参数去掉了,测试也可行http://shop.10010.com/number/doGetNumberList.action?searchNumberInfo.order=0&pageInfo.currPage=【3g分页】&searchNumberInfo.netType=01&searchNumberInfo.searchRuleID=&searchNumberInfo.numberStartCost=&searchNumberInfo.numberCardId=路这个就是列表的第4页:可以浏览器打开,下载文件,记事本打开,就是该页请求返回的数据http://shop.10010.com/number/doGetNumberList.action?searchNumberInfo.order=0&pageInfo.currPage=3&searchNumberInfo.netType=01&searchNumberInfo.searchRuleID=&searchNumberInfo.numberStartCost=&searchNumberInfo.numberCardId=内容页自定义网址格式:http://shop.10010.com/number/searchOneNumber.action?searchNumberInfo.cardID=[参数1]&searchNumberInfo.numbercityId=[参数2]&searchNumberInfo.netType=01,注意这3个参数都不可以少,而且要符合当前城市和网络类型
是3g的,当然searchNumberInfo.netType=01,改为00提示系统繁忙,就是错误,同样做了裁剪
可以尝试用登录,用抓包的cooike,分别抓取不同城市的cooike,也许可行,同时进行多个城市的采集,要不不用登录,浏览器切换城市后,你采集时就是这个城市的号码
下面是post参数的说明,可以对应设置:formname=defaultnumber--------表单名字
searchNumberInfo.order------3g0按上架时间排序1,2互换按预存款排序,奇偶
searchNumberInfo.order2g--------2g0按上架时间排序1,2互换按预存款排序,奇偶
pageInfo.currPage-------3g当前页,等于输入页数-1
pageInfo.totalPager=86-----3g总页数
searchNumberInfo.currPage2g--------2g当前页,等于输入页数-1
searchNumberInfo.totalPager2g=1012-------2g总页数
searchNumberInfo.cardID---------号码
searchNumberInfo.isreserve=00是保留ajax后设置
searchNumberInfo.saleCost=0-------销售成本,ajax后设置
searchNumberInfo.numbercountryId-------城市id
searchNumberInfo.numbercityId ------------城市id
searchNumberInfo.ruleID=-9999--------ajax后设置,靓号类型
searchNumberInfo.startCost=0----------ajax后设置,预存款
searchNumberInfo.onnetlong=0---------净长
searchNumberInfo.lowestcost=0-----------最低价
searchNumberInfo.nCardcost=0----------- nCardcost = infoList.nCardcost==undefined?"0":infoList.nCardcost;
searchNumberInfo.payType=01--------支付类型,ajax后设置
searchNumberInfo.processType=numbercard--------
searchNumberInfo.netType=01---------网络类型 00:2g 01:3g选择3g 01,2g 00
searchNumberInfo.searchRuleID------------3g靓号类型
searchNumberInfo.numberStartCost---------3g预存款
searchNumberInfo.numberCardId-------3g自定义
searchNumberInfo.searchRuleID2g-------2g靓号类型
searchNumberInfo.numberStartCost2g--------2g预存款
searchNumberInfo.numberCardId2g=--------2g自定义这个网站很整洁,还有注释,分析就比较方便,主要的几个js文件 searchnumber ;jquery.ajaxpager3g;jquery.ajaxpager2g;jquery.cookie;left;mydata
说的很多,要采集这个站这些参数的意识必须搞明白,才可以任意采集
高手啊 但是新手未必看得懂啊 {:4_180:}楼主辛苦了 直接用你那个规则采不了呀? 这么楼主,真是有空啊.总是免费给人做事.佩服. 这样的精神给力啊,支持啊 楼主解释得非常详细。 高手啊,现在还看不明白 给力!!!!!!!
虽然不是非常明白!但是让我迷惑多天的问题有了解决方案了大力支持 顶!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
页:
[1]
2