zoukankan      html  css  js  c++  java
  • 记录一次重新学习SetInternal和SetTimeout

     背景:
    做一个Chrome的TamperMoney脚本,采集超星慕课全部学校:http://passport2.chaoxing.com/login?fid=145&refer=http://i.mooc.chaoxing.com
    这是一个二级联动的,左侧是城市、右上是26个字母,右下是要采集的学校列表,想要一次性把全部数据采集下来,必须不断点击城市和字母进行切换,数据是通过ajax异步加载后渲染到页面的。
    总的来说是希望前端抓取到学校的名称和ID,用$.ajax传到自己写的ashx的方法中,再存到数据库里。

    坑一:首先遇到的问题就是这样采集的数据由于跨域问题,无法$.ajax到localhost:1066/r.ashx?method=a 中,解决方式是使用JSONP

     $.ajax({
            url: "http://localhost:1066/handle/r.ashx?method=updateChaoXingSchool",
            type: "get",
            dataType:"jsonp", //使用jsonp
            jsonp:"jsonpCallback",
            jsonpCallback:"success_jsonpCallback", 
            data: {schoolId:id,name:name,letter:lt},
            success:function(result){
                csl++;
            },
            error:function(data){
            }
        });


    后端context.response.write也必须和jsonpCallback中制定的方法名一致才行,里面的内容倒是无关紧要:
    context.Response.Write("success_jsonpCallback({"result":true})");


    思路一:使用$.each嵌套循环来做,但是$.each是异步的,而JSONP也是异步的且无法强制设定为同步,就算是可以同步,也会阻挡网页导致点击事件失效,这样切换城市和字母又无法实现了。

    思路二:使用for循环+sitetimeout,因为for循环是同步方法,settimeout可以控制$.ajax的运行间隔。 用过才深刻理解了setTimeout是个异步方法,换用了各种方式设定setTimeout(如i*1000)效果也非常差,即使顺序和内容采集到是对的,也会导致浏览器卡顿崩溃。

    思路三:前面的尝试让我彻底放弃了使用循环来实现,改变使用定时器SetInternal实现:定时监控整个网页的情况,来判定如何执行采集。原理:
        1、点击启动按钮:获取城市对象集合、当前学校对象集合;设定初始值,如起始城市、字母、学校的 Inex值。
        2、设定定时器A,每0.1秒采集当前页面的学校,当前学校Index自增   
        3、if(当前学校Index==当前页面总学校数)  
                                then  
                                      清除定时器A,避免在切换字母的过程中继续采集
                                      点击切换下一个字母
             else
                                采集学校数据……
     4、 设定定时器B
    5、
    if(当前字母Index==26)  
                                then  
                                      清除定时器B,避免在切换城市的过程中继续采集
                                      点击切换下一个城市
             else
                                采集学校数据……
                                       

    最终代码:

    // ==UserScript==
    // @name         超星采集学校
    // @namespace    http://tampermonkey.net/
    // @version      0.1
    // @description  try to take over the world!
    // @author       You
    // @match        http://passport2.chaoxing.com/*
    // @require http://code.jquery.com/jquery-1.10.0.min.js
    // @grant        none
    // ==/UserScript==
    //当前总
    var cl=$(".zw_s_li a").length;
    var ll=26;
    var sl=$(".zw_m_li a").length;
    //当前进度
    var ccl=0;
    var cll=1;
    var csl=0;
    //当前对象
    var city=$(".zw_s_li a");
    var school=$(".zw_m_li a");
    var letter=$(".zw_m_t_li a");
    var timerA;
    var timerB;
    
    function getSchool(){
        if(cll>ll){
            clearInterval(timerB);
            //如果字母都过完了,就换城市
            ccl++;
            cll=1;//重置字母
            $(city[ccl]).click();
            setTimeout(function(){
                $(letter[1]).click();
                timerB=setInterval(function(){
                    getSchool();
                },1000);
            },2000);
        }
        else if(ccl>cl){
            clearInterval(timerB);
            return;
        }
        else if(csl==sl){
            //如果学校采集完了,就换字母
            clearInterval(timerB);
            cll++;
            console.log($(letter[cll]).attr("id"));
            $(letter[cll]).click();
            setTimeout(function(){
                school=$(".zw_m_li a");
                csl=0;
                sl=school.length;
                timerB=setInterval(function(){
                    getSchool();
                },1000);
            },2000);
        }
        else{
            //否则一直采集学校
            console.log(ccl+"_"+cll+"/"+ll+"_"+csl+"/"+sl);
            var id=$(school[csl]).attr("id");
            var name=$(school[csl]).attr("name");
            var lt=$(letter[cll]).attr("id");
            csl++;
            insertSchool(id,name,lt);
            getSchool();
        }
    }
    function insertSchool(id,name,lt){
        $.ajax({
            url: "http://localhost:1066/handle/r.ashx?method=updateChaoXingSchool",
            type: "get",
            dataType:"jsonp",
            jsonp:"jsonpCallback",
            jsonpCallback:"success_jsonpCallback",
            data: {schoolId:id,name:name,letter:lt},
            success:function(result){
            },
            error:function(data){
            }
        });
    }
    (function() {
    
        $(".zw_m_box").before("<input type='button' value='采集' style='200px;height:35px;text-align:center;font-size:16px;' id='caiji'>");
        $("#caiji").click(function(){
            cl=$(".zw_s_li a").length;
            sl=$(".zw_m_li a").length;
            city=$(".zw_s_li a");
            school=$(".zw_m_li a");
            letter=$(".zw_m_t_li a");
            getSchool();
        });
    })();
  • 相关阅读:
    入侵特斯拉——智能汽车安全性分析
    D-Link系列路由器漏洞挖掘入门
    工控安全入门之 Ethernet/IP
    浅谈JS数据类型存储问题
    【备忘】12306购票必杀技
    制作炫酷的专题页面
    杂记(下)
    杂记(上)
    跨域请求解决方案
    好用的表单验证插件
  • 原文地址:https://www.cnblogs.com/cdoneiX/p/12258522.html
Copyright © 2011-2022 走看看