爬虫之补环境脚本:脱环境

该脚本需要在浏览器内运行

javascript 复制代码
//获取原型环境代码
let getProtoEnvCode = function getProtoEnvCode(proto, instanceObj) {
    //proto:原型函数
    //instanceObj:实例对象,可选参数 传的话会添加默认值
    let code = "";
    let protoName = proto.name;
    //添加注释
    code += `// ${protoName}对象\r\n`;
    //定义原型
    code += `${protoName} = function ${protoName}(){`;
    try {
        new proto;
    } catch (e) {
        code += `return bodavm.toolsFunc.throwError('${e.name}','${e.message}');`;
    }

    code += `}\r\n`;
    //保护原型
    code += `bodavm.toolsFunc.safeProto(${protoName},"${protoName}");\r\n`;
    //设置原型链
    let protoObj = proto.prototype;
    let proto_protoName = Object.getPrototypeOf(protoObj)[Symbol.toStringTag];//原型对象的原型的名称,父级原型名称
    if (proto_protoName !== undefined) {//在存在父级的情况下设置原型
        code += `Object.setPrototypeOf(${protoName}.prototype,${proto_protoName}.prototype);\r\n`;
    }

    //设置原型属性
    for (const key in Object.getOwnPropertyDescriptors(proto)) {
        if (key === "arguments" || key === "caller" || key === "length" || key === "name" || key === "prototype") {
            continue;
        }
        let descriptor = getDescriptor(proto, key, protoName, protoName, instanceObj);
        code += `bodavm.toolsFunc.defineProperty(${protoName},"${key}",${descriptor});\r\n`;
    }
    //设置原型对象的属性
    for (const key in Object.getOwnPropertyDescriptors(proto.prototype)) {
        if (key === "constructor") {
            continue;
        }
        let descriptor = getDescriptor(proto.prototype, key, `${protoName}.prototype`, protoName, instanceObj);
        code += `bodavm.toolsFunc.defineProperty(${protoName}.prototype,"${key}",${descriptor});\r\n`;
    }

    console.log(code);
    copy(code);
    //return code;
}

//获取实例对象的环境代码
let getObjEnvCode = function getObjEnvCode(obj, objName, instanceObj) {
    //obj 实例对象
    //objName 实例对象名称
    //instanceObj 实例对象 传输的话设置默认值
    let code = "";
    //添加注释
    code += `// ${objName}对象\r\n`;
    //定义对象
    code += `${objName} = {}\r\n`;
    //设置原型
    let protoName = Object.getPrototypeOf(obj)[Symbol.toStringTag];
    if (protoName != undefined) {
        code += `Object.setPrototypeOf(${objName},${protoName}.prototype);\r\n`;
    }

    //设置对象属性
    for (const key in Object.getOwnPropertyDescriptors(obj)) {
        let descriptor = getDescriptor(obj, key, objName, objName, instanceObj);
        code += `bodavm.toolsFunc.defineProperty(${objName},"${key}",${descriptor});\r\n`;
    }

    console.log(code);
    copy(code);
    //return code;
}

//获取属性描述符
let getDescriptor = function getDescriptor(obj, prop, objName, protoName, instanceObj) {
    let descriptor = Object.getOwnPropertyDescriptor(obj, prop);
    let configurable = descriptor.configurable;
    let enumerable = descriptor.enumerable;
    let code = `{configurable:${configurable}, enumerable:${enumerable}, `;
    if (descriptor.hasOwnProperty("writable")) {
        let writable = descriptor.writable;
        code += `writable:${writable}, `;
    }
    if (descriptor.hasOwnProperty("value")) {
        let value = descriptor.value;
        if (value instanceof Object) {
            if (typeof value === "function") {
                code += `value:function(){return bodavm.toolsFunc.dispatch(this,${objName},"${protoName}","${prop}",arguments);}`;

            } else {
                //需要关注
                console.log("需要额外关注", value);
                //JSON.stringify(value)//如果不是非循环引用可以这样转化值
                code = `value:{}`;
            }
        } else if (typeof value === "symbol") {
            code += `value:${value.toString()}`;
        } else if (typeof value === "string") {
            code += `value:"${value}"`;
        } else {
            code += `value:${value}`;
        }
    }

    if (descriptor.hasOwnProperty("get")) {//有默认值
        let get = descriptor.get;
        if (typeof get === "function") {
            let defaultValue;
            try {
                defaultValue = get.call(instanceObj);//获取属性值 Object.getOwnPropertyDescriptor(window,'name').get.call(window)
            } catch (e) {

            }

            if (defaultValue == undefined || defaultValue instanceof Object) {
                code += `get:function(){return bodavm.toolsFunc.dispatch(this,${objName},"${protoName}","${prop}_get",arguments);}, `;
            } else {
                if (typeof defaultValue === 'string') {
                    code += `get:function(){return bodavm.toolsFunc.dispatch(this,${objName},"${protoName}","${prop}_get",arguments,'${defaultValue}');}, `;
                } else if (typeof value === "symbol") {
                    code += `get:function(){return bodavm.toolsFunc.dispatch(this,${objName},"${protoName}","${prop}_get",arguments,${defaultValue.toString()});}, `;
                } else {
                    code += `get:function(){return bodavm.toolsFunc.dispatch(this,${objName},"${protoName}","${prop}_get",arguments,${defaultValue});}, `;
                }
            }

        } else {
            code += `get:undefined, `;
        }
    }

    if (descriptor.hasOwnProperty("set")) {//没有默认值
        let set = descriptor.set;
        if (typeof set === "function") {
            code += `set:function(){return bodavm.toolsFunc.dispatch(this,${objName},"${protoName}","${prop}_set",arguments);}`;
        } else {
            code += `set:undefined`;
        }
    }

    code += "}";
    return code;
}


// 在浏览器执行代码
// getProtoEnvCode(Window);
//getObjEnvCode(window,"window")
相关推荐
禁止摆烂_才浅14 小时前
JavaScript 高级面试题
前端·javascript·面试
禁止摆烂_才浅14 小时前
JavaScript 基础 高频面试题
前端·javascript·面试
无糖可可果14 小时前
从零理解 Docker:为什么我的代码在你的电脑上跑不起来?
javascript·后端
跨境技工小黎14 小时前
IPFoxy动态住宅IP实测:做数据采集和爬虫可行吗?
爬虫·网络协议·tcp/ip
玫瑰互动GEO15 小时前
企业官网SEO优化技术架构:从服务器配置到爬虫友好的全链路实践
爬虫·架构
Dxy123931021616 小时前
Python XPath position() 完整使用指南,避坑合集(lxml适用)
前端·javascript·python
名字还没想好☜16 小时前
React 19 useOptimistic 实战:点赞评论先更新 UI,失败自动回滚
前端·javascript·react.js·ui·react·useoptimistic
海鸥两三16 小时前
【websocket合集2】websocket.js源码解析和页面调用示例
javascript·websocket·网络协议
梅孔立16 小时前
Docker 部署 Python3\.11 Flask爬虫项目 终极稳定教程(解决线程报错/挂载失效/pip报错)
爬虫·docker·flask
vipbic1 天前
一个前端的 9 天重构:我是怎么用 Codex 重做航栈的
前端·javascript·后端