zhouchanglin 发表于 2010-12-26 20:39:13

中国联通采集实例

采集的目标站,中国联通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("按预存款排序&nbsp;&darr;");
            gotopage3g();
      }else{
            $('#order').val("2");
            $('#sorttime').removeClass('sort_on').addClass('sort_out');$('#sorttime').html("按上架时间排序");
            $('#sortcost').addClass('sort_on');   $('#sortcost').html("按预存款排序&nbsp;&uarr;");
            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;'>&nbsp;</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;'>&nbsp;</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 + "页&nbsp;到第");
    $('#totalnumpageh').empty().html(nowpage + "&frasl;" + totalPager + "页&nbsp;到第");
    $('#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

说的很多,要采集这个站这些参数的意识必须搞明白,才可以任意采集


专业收费采集 发表于 2010-12-26 22:42:59

高手啊 但是新手未必看得懂啊

okok7845 发表于 2010-12-26 23:56:04

{:4_180:}楼主辛苦了

blwxy123 发表于 2010-12-27 14:17:46

直接用你那个规则采不了呀?

dougeng 发表于 2010-12-27 21:43:53

这么楼主,真是有空啊.总是免费给人做事.佩服.

zk1062 发表于 2011-1-19 11:09:27

这样的精神给力啊,支持啊

zhouping0011 发表于 2011-2-17 11:04:07

楼主解释得非常详细。

askzs 发表于 2011-3-1 15:41:52

高手啊,现在还看不明白

power11 发表于 2011-3-11 12:05:07

给力!!!!!!!
    虽然不是非常明白!但是让我迷惑多天的问题有了解决方案了大力支持

415439444 发表于 2011-3-27 13:27:30

顶!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
页: [1] 2
查看完整版本: 中国联通采集实例