diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/0.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/0.json deleted file mode 100644 index f389d29..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/0.json +++ /dev/null @@ -1 +0,0 @@ -{"id":0,"name":"新闻中心 - 小鱼易连-官网-让世界零距离","url":"https://www.xylink.com/news","links":"https://www.xylink.com/news","create_time":"6/27/2023, 1:34:26 AM","version":"0.3.2","containJudge":true,"desc":"https://www.xylink.com/news","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.xylink.com/news","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.xylink.com/news"}],"outputParameters":[{"id":0,"name":"参数2_文本","desc":"","type":"string","exampleValue":"亮相西部数博会,小鱼易连云视频助力数字经济高质量发展"}],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,8,12],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.xylink.com/news","links":"https://www.xylink.com/news","maxWaitTime":20,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":4,"index":2,"parentId":3,"type":1,"option":8,"title":"循环","sequence":[9,7,3,13,15],"isInLoop":true,"position":0,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":"2","pathList":"/html/body/div[1]/div/div[2]/section/div/div[2]/div/div[1]/div[2]/div[1]/div[1]\n/html/body/div[1]/div/div[2]/section/div/div[2]/div/div[2]/div[2]/div[1]/div[1]","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":3,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":""}},{"id":8,"index":3,"parentId":4,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":true,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":true,"xpath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[1]","wait":10,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":"","loopType":1}},{"id":-1,"index":4,"parentId":6,"type":1,"option":8,"title":"循环","sequence":[5],"isInLoop":true,"position":1,"parameters":{"history":5,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":1,"pathList":"","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":["/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[1]","//div[contains(., '亮相西部数博会,小鱼')]","//DIV[@class='xyEditor__index_title']"]}},{"id":-1,"index":5,"parentId":11,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":5,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":true,"name":"参数1_文本","desc":"","extractType":0,"relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"亮相西部数博会,小鱼易连云视频助力数字经济高质量发展"},{"num":1,"value":"2023-06-20    小鱼易连"},{"num":2,"value":"6月16-18日,由西安市人民政府、陕西省工业和信息化厅、陕西省互联网信息办公室、陕西省科学技术厅、陕西省通信管理局主办,以“数字创享 原启未来”为主题的第四届西部数字经济博览会(以下简称西部数博会)在陕西西安举办,活动重点展示陕西深入实施创新驱动发展战略成果,充分发挥深化西部数实深度融合发展的桥梁作用,推进西部数字经济高质量发展。\n \n\n\n\n \n小鱼易连携安全可信云视频,亮相中国电子云-中国信创云主题展区,与阿里巴巴、中软国际、太极股份、科大讯飞、东软集团、商汤科技、新华三等300余家数字化领域头部企业,共同展示数字创新成果,分享“数实融合”经验,以创新合力共同助力数字政府、智慧政法、央国企数字化、智慧金融、智慧教育、智慧医疗建设,促进数字经济高质量发展。\n \n\n数字创享 原启未来\n小鱼易连信创云视频筑牢数字底座\n\n \n\n党的二十大报告提出要“加快发展数字经济,促进数字经济和实体经济深度融合,打造具有国际竞争力的数字产业集群”。\n \n西部数博会以“数字创享 原启未来”为主题,旨在全面推动西部地区数字经济与实体经济深度融合。作为迄今为止西北地区最大的数字主题盛会,西部数博会搭建起西部数字经济创新发展、产业融合、交流合作的综合平台,成为搭建数字头部企业合作桥梁、引领数字经济发展的标志性盛会,也成为推进数字经济高质量发展的新引擎。\n \n小鱼易连以安全可信的自主技术,通过SVC+AVC双引擎和虚拟化部署架构,打造“云视频平台+云视频终端+开发平台”的信创解决方案,并满足对主流国产处理器、国产操作系统、国产数据库的全兼容,实现方案对各行各业场景的广泛适配和深入融合,期望以安全、创新的信创云视频驱动产业数字化和数字产业化发展。\n \n活动现场,小鱼易连面向领导嘉宾展示了“高安全·超融合·全连接”的云视频整体解决方案,一体化的云视频终端、4K专业智能终端以及能适用于大中小型会议室的全场景终端,能够为各类会议室、室内外的多场景,提供安全、稳定、高品质的视频应用和便捷协作,小鱼易连的系列产品获得了诸多领导嘉宾的好评和肯定。\n\n \n\n\n\n \n\n聚焦场景 数实融合\n云视频促进数字经济高质量发展\n\n \n\n随着“数实融合”不断加快场景创新、渗透应用、优化迭代,其催生的新模式、新业态将激活经济潜能,助力数字经济高质量发展。\n \n小鱼易连用云视频逐渐弥合“数字鸿沟”,基于中国电子PKS体系,构建PKSV可信云视频平台,深度融合视频会议、直播、点播、语音、监控等视讯功能,创新构建的会议会商、互联网+政务、协同办公、应急指挥、疫情防控、党建培训、远程教学、移动会议、执法巡查等应用,是“数实融合”深入发展的创新成果和必然结果,对高质量发展具有积极意义。\n \n在“数实融合”催生出的诸多云视频新场景赋能下,小鱼易连为政务、政法、企业、金融、教育、医疗等全行业数字化转型注入新活力。\n\n \n\n\n政务领域,云视频突破信息孤岛,实现省、市、县、乡、村多级可视化联动。\n\n\n政法领域,云视频深入业务全流程,提升司法行政效率和公共法律服务水平。\n\n\n企业领域,云视频融合央国企业务链路,助推跨级、跨部门协同高质效。\n\n\n金融行业,云视频全面适配行业场景,优化业务流程、加速数字化转型。\n\n\n教育行业,云视频为老师、学生构建沉浸式互动课堂,加速教育公平均衡。\n\n\n医疗领域,云视频为远程医疗提供支撑,促进分级诊疗、优化资源配置。\n\n\n \n\n\n\n \n\n数字化发展正加速向千行百业渗透,小鱼易连积极推动数字经济纵深发展。依托多年来的丰富积累和实践,小鱼易连已经为国家部委、政府机构和央国企等在内的各行各业16万家大中型客户提供服务,中华人民共和国水利部、国家税务总局、中华人民共和国审计署、广西壮族自治区人民政府、中国电子等应用云视频,开启全面的数字化转型和升级。\n蓬勃发展的数字经济已成为我国加快推进经济高质量发展的重要抓手,小鱼易连首当其冲,基于云视频的全栈资源、国产化平台、更优质的服务、更开放的生态,推动千行百业数字化,通过云视频对产业进行的全方位、全链条升级,充分激发数字技术对经济发展的倍增作用,从而为高质量发展提供有力支撑。\n"},{"num":3,"value":"Preview"}],"unique_index":"bxil6tnn2jlljd20x9i","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":11,"index":6,"parentId":7,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":5,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"ant-pagination-next\")]/button[1]","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[2]/ul[1]/li[7]/button[1]","//button[contains(., '')]","//BUTTON[@class='ant-pagination-item-link']"]}},{"id":7,"index":7,"parentId":4,"type":1,"option":8,"title":"循环","sequence":[6,10],"isInLoop":true,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":"5","pathList":"","textList":"","code":"return t_a < v_a","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0}},{"id":2,"index":8,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"v_a = 0;","waitTime":0,"recordASField":0}},{"id":6,"index":9,"parentId":4,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"t_a = 0;","waitTime":0,"recordASField":0}},{"id":12,"index":10,"parentId":7,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":true,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"t_a = t_a + 1;","waitTime":0,"recordASField":0}},{"id":5,"index":11,"parentId":3,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":true,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"console.log(v_a);\nv_a = v_a + 1;\nconsole.log(v_a);","waitTime":0,"recordASField":0}},{"id":3,"index":12,"parentId":0,"type":1,"option":8,"title":"循环","sequence":[2,11],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":"5","pathList":"","textList":"","code":"return v_a < 24;","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0}},{"id":9,"index":13,"parentId":4,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":3,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数2_文本","desc":"","relativeXPath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[1]","allXPaths":["/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[1]","//div[contains(., '亮相西部数博会,小鱼')]","//DIV[@class='xyEditor__index_title']"],"exampleValues":[{"num":0,"value":"亮相西部数博会,小鱼易连云视频助力数字经济高质量发展"}],"unique_index":"xuh40ko20yljd2j8fr","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":14,"index":14,"parentId":13,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"history.go(-1);","waitTime":0,"recordASField":0}},{"id":10,"index":15,"parentId":4,"type":2,"option":9,"title":"判断条件","sequence":[16],"isInLoop":true,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0}},{"id":13,"parentId":10,"index":16,"type":3,"option":10,"title":"条件分支","sequence":[14],"isInLoop":true,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"class":"5","value":"","code":"return v_a > 0;","waitTime":0},"position":0},{"id":-1,"parentId":10,"index":17,"type":3,"option":10,"title":"条件分支","sequence":[],"isInLoop":true,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"class":0,"value":"","code":"","waitTime":0},"position":1}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/1.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/1.json deleted file mode 100644 index 93030ca..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/1.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"name":"新闻中心 - 小鱼易连-官网-让世界零距离","url":"https://www.xylink.com/news","links":"https://www.xylink.com/news","create_time":"6/27/2023, 1:44:49 AM","version":"0.3.2","containJudge":true,"desc":"https://www.xylink.com/news","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.xylink.com/news","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.xylink.com/news"}],"outputParameters":[{"id":0,"name":"参数2_文本","desc":"","type":"string","exampleValue":"亮相西部数博会,小鱼易连云视频助力数字经济高质量发展"}],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,8,12],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.xylink.com/news","links":"https://www.xylink.com/news","maxWaitTime":20,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":4,"index":2,"parentId":3,"type":1,"option":8,"title":"循环点击每个文章标题","sequence":[9,7,3,13,15],"isInLoop":true,"position":0,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":"2","pathList":"/html/body/div[1]/div/div[2]/section/div/div[2]/div/div[1]/div[2]/div[1]/div[1]\n/html/body/div[1]/div/div[2]/section/div/div[2]/div/div[2]/div[2]/div[1]/div[1]","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":3,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":""}},{"id":8,"index":3,"parentId":4,"type":0,"option":2,"title":"点击标题进详情页","sequence":[],"isInLoop":true,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":true,"xpath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[1]","wait":10,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":"","loopType":1}},{"id":-1,"index":4,"parentId":6,"type":1,"option":8,"title":"循环","sequence":[5],"isInLoop":true,"position":1,"parameters":{"history":5,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":1,"pathList":"","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":["/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[1]","//div[contains(., '亮相西部数博会,小鱼')]","//DIV[@class='xyEditor__index_title']"]}},{"id":-1,"index":5,"parentId":11,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":5,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":true,"name":"参数1_文本","desc":"","extractType":0,"relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"亮相西部数博会,小鱼易连云视频助力数字经济高质量发展"},{"num":1,"value":"2023-06-20    小鱼易连"},{"num":2,"value":"6月16-18日,由西安市人民政府、陕西省工业和信息化厅、陕西省互联网信息办公室、陕西省科学技术厅、陕西省通信管理局主办,以“数字创享 原启未来”为主题的第四届西部数字经济博览会(以下简称西部数博会)在陕西西安举办,活动重点展示陕西深入实施创新驱动发展战略成果,充分发挥深化西部数实深度融合发展的桥梁作用,推进西部数字经济高质量发展。\n \n\n\n\n \n小鱼易连携安全可信云视频,亮相中国电子云-中国信创云主题展区,与阿里巴巴、中软国际、太极股份、科大讯飞、东软集团、商汤科技、新华三等300余家数字化领域头部企业,共同展示数字创新成果,分享“数实融合”经验,以创新合力共同助力数字政府、智慧政法、央国企数字化、智慧金融、智慧教育、智慧医疗建设,促进数字经济高质量发展。\n \n\n数字创享 原启未来\n小鱼易连信创云视频筑牢数字底座\n\n \n\n党的二十大报告提出要“加快发展数字经济,促进数字经济和实体经济深度融合,打造具有国际竞争力的数字产业集群”。\n \n西部数博会以“数字创享 原启未来”为主题,旨在全面推动西部地区数字经济与实体经济深度融合。作为迄今为止西北地区最大的数字主题盛会,西部数博会搭建起西部数字经济创新发展、产业融合、交流合作的综合平台,成为搭建数字头部企业合作桥梁、引领数字经济发展的标志性盛会,也成为推进数字经济高质量发展的新引擎。\n \n小鱼易连以安全可信的自主技术,通过SVC+AVC双引擎和虚拟化部署架构,打造“云视频平台+云视频终端+开发平台”的信创解决方案,并满足对主流国产处理器、国产操作系统、国产数据库的全兼容,实现方案对各行各业场景的广泛适配和深入融合,期望以安全、创新的信创云视频驱动产业数字化和数字产业化发展。\n \n活动现场,小鱼易连面向领导嘉宾展示了“高安全·超融合·全连接”的云视频整体解决方案,一体化的云视频终端、4K专业智能终端以及能适用于大中小型会议室的全场景终端,能够为各类会议室、室内外的多场景,提供安全、稳定、高品质的视频应用和便捷协作,小鱼易连的系列产品获得了诸多领导嘉宾的好评和肯定。\n\n \n\n\n\n \n\n聚焦场景 数实融合\n云视频促进数字经济高质量发展\n\n \n\n随着“数实融合”不断加快场景创新、渗透应用、优化迭代,其催生的新模式、新业态将激活经济潜能,助力数字经济高质量发展。\n \n小鱼易连用云视频逐渐弥合“数字鸿沟”,基于中国电子PKS体系,构建PKSV可信云视频平台,深度融合视频会议、直播、点播、语音、监控等视讯功能,创新构建的会议会商、互联网+政务、协同办公、应急指挥、疫情防控、党建培训、远程教学、移动会议、执法巡查等应用,是“数实融合”深入发展的创新成果和必然结果,对高质量发展具有积极意义。\n \n在“数实融合”催生出的诸多云视频新场景赋能下,小鱼易连为政务、政法、企业、金融、教育、医疗等全行业数字化转型注入新活力。\n\n \n\n\n政务领域,云视频突破信息孤岛,实现省、市、县、乡、村多级可视化联动。\n\n\n政法领域,云视频深入业务全流程,提升司法行政效率和公共法律服务水平。\n\n\n企业领域,云视频融合央国企业务链路,助推跨级、跨部门协同高质效。\n\n\n金融行业,云视频全面适配行业场景,优化业务流程、加速数字化转型。\n\n\n教育行业,云视频为老师、学生构建沉浸式互动课堂,加速教育公平均衡。\n\n\n医疗领域,云视频为远程医疗提供支撑,促进分级诊疗、优化资源配置。\n\n\n \n\n\n\n \n\n数字化发展正加速向千行百业渗透,小鱼易连积极推动数字经济纵深发展。依托多年来的丰富积累和实践,小鱼易连已经为国家部委、政府机构和央国企等在内的各行各业16万家大中型客户提供服务,中华人民共和国水利部、国家税务总局、中华人民共和国审计署、广西壮族自治区人民政府、中国电子等应用云视频,开启全面的数字化转型和升级。\n蓬勃发展的数字经济已成为我国加快推进经济高质量发展的重要抓手,小鱼易连首当其冲,基于云视频的全栈资源、国产化平台、更优质的服务、更开放的生态,推动千行百业数字化,通过云视频对产业进行的全方位、全链条升级,充分激发数字技术对经济发展的倍增作用,从而为高质量发展提供有力支撑。\n"},{"num":3,"value":"Preview"}],"unique_index":"bxil6tnn2jlljd20x9i","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":11,"index":6,"parentId":7,"type":0,"option":2,"title":"点击下一页","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":5,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"ant-pagination-next\")]/button[1]","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[2]/ul[1]/li[7]/button[1]","//button[contains(., '')]","//BUTTON[@class='ant-pagination-item-link']"]}},{"id":7,"index":7,"parentId":4,"type":1,"option":8,"title":"While t_a < v_a","sequence":[6,10],"isInLoop":true,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":"5","pathList":"","textList":"","code":"return t_a < v_a","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0}},{"id":2,"index":8,"parentId":0,"type":0,"option":5,"title":"v_a = 0","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"v_a = 0;","waitTime":0,"recordASField":0}},{"id":6,"index":9,"parentId":4,"type":0,"option":5,"title":"t_a = 0","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"t_a = 0;","waitTime":0,"recordASField":0}},{"id":12,"index":10,"parentId":7,"type":0,"option":5,"title":"t_a = t_a + 1","sequence":[],"isInLoop":true,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"t_a = t_a + 1;","waitTime":0,"recordASField":0}},{"id":5,"index":11,"parentId":3,"type":0,"option":5,"title":"v_a = v_a + 1","sequence":[],"isInLoop":true,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"v_a = v_a + 1;","waitTime":0,"recordASField":0}},{"id":3,"index":12,"parentId":0,"type":1,"option":8,"title":"While v_a < 24","sequence":[2,11],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":"5","pathList":"","textList":"","code":"return v_a < 24;","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0}},{"id":9,"index":13,"parentId":4,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":3,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数2_文本","desc":"","relativeXPath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[1]","allXPaths":["/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[1]","//div[contains(., '亮相西部数博会,小鱼')]","//DIV[@class='xyEditor__index_title']"],"exampleValues":[{"num":0,"value":"亮相西部数博会,小鱼易连云视频助力数字经济高质量发展"}],"unique_index":"xuh40ko20yljd2j8fr","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":14,"index":14,"parentId":13,"type":0,"option":5,"title":"history.go(-1)","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"history.go(-1);","waitTime":0,"recordASField":0}},{"id":10,"index":15,"parentId":4,"type":2,"option":9,"title":"判断条件","sequence":[16],"isInLoop":true,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0}},{"id":13,"parentId":10,"index":16,"type":3,"option":10,"title":"IF v_a > 0","sequence":[14],"isInLoop":true,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"class":"5","value":"","code":"return v_a > 0;","waitTime":0},"position":0},{"id":-1,"parentId":10,"index":17,"type":3,"option":10,"title":"条件分支","sequence":[],"isInLoop":true,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"class":0,"value":"","code":"","waitTime":0},"position":1}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/10.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/10.json deleted file mode 100644 index e31c127..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/10.json +++ /dev/null @@ -1 +0,0 @@ -{"id":10,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:33:22 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3,8,10,11],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//span[contains(., '上海')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":4,"index":8,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":9,"parentId":0,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数1_文本","desc":"","relativeXPath":"/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"],"exampleValues":[{"num":0,"value":"\n \n \n "}],"unique_index":"1ri57q6vri5ljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":1,"contentType":0,"relative":false,"name":"参数2_链接文本","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":"新加坡"}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":false,"name":"参数3_链接地址","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":""}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":5,"index":10,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"//a[contains(., '东京')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[]}},{"id":6,"index":11,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":5,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/11.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/11.json deleted file mode 100644 index 7b8034f..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/11.json +++ /dev/null @@ -1 +0,0 @@ -{"id":11,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:33:57 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3,8,10,11],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//span[contains(., '上海')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":4,"index":8,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":9,"parentId":0,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数1_文本","desc":"","relativeXPath":"/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"],"exampleValues":[{"num":0,"value":"\n \n \n "}],"unique_index":"1ri57q6vri5ljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":1,"contentType":0,"relative":false,"name":"参数2_链接文本","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":"新加坡"}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":false,"name":"参数3_链接地址","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":""}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":5,"index":10,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"//a[contains(., '东京')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[]}},{"id":6,"index":11,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":5,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/12.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/12.json deleted file mode 100644 index d6b4dda..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/12.json +++ /dev/null @@ -1 +0,0 @@ -{"id":12,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:33:57 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3,8,10,11],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//span[contains(., '上海')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":4,"index":8,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":9,"parentId":0,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数1_文本","desc":"","relativeXPath":"/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"],"exampleValues":[{"num":0,"value":"\n \n \n "}],"unique_index":"1ri57q6vri5ljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":1,"contentType":0,"relative":false,"name":"参数2_链接文本","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":"新加坡"}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":false,"name":"参数3_链接地址","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":""}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":5,"index":10,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"//a[contains(., '东京')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[]}},{"id":6,"index":11,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":5,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/13.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/13.json deleted file mode 100644 index 919695f..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/13.json +++ /dev/null @@ -1 +0,0 @@ -{"id":13,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:39:38 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3,8,10,11],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//span[contains(., '上海')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":4,"index":8,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":9,"parentId":0,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数1_文本","desc":"","relativeXPath":"/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"],"exampleValues":[{"num":0,"value":"\n \n \n "}],"unique_index":"1ri57q6vri5ljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":1,"contentType":0,"relative":false,"name":"参数2_链接文本","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":"新加坡"}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":false,"name":"参数3_链接地址","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":""}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":5,"index":10,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"//a[contains(., '东京')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[]}},{"id":6,"index":11,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":5,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/14.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/14.json deleted file mode 100644 index a625451..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/14.json +++ /dev/null @@ -1 +0,0 @@ -{"id":14,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:40:51 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3,8,10,11],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//a[contains(., '上海')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":4,"index":8,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":9,"parentId":0,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数1_文本","desc":"","relativeXPath":"/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"],"exampleValues":[{"num":0,"value":"\n \n \n "}],"unique_index":"1ri57q6vri5ljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":1,"contentType":0,"relative":false,"name":"参数2_链接文本","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":"新加坡"}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":false,"name":"参数3_链接地址","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":""}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":5,"index":10,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"//a[contains(., '东京')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[]}},{"id":6,"index":11,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":5,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/15.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/15.json deleted file mode 100644 index 20a48b7..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/15.json +++ /dev/null @@ -1 +0,0 @@ -{"id":15,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:43:01 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3,8,10,11],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//span[contains(., 'CNSHA上海')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":4,"index":8,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":9,"parentId":0,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数1_文本","desc":"","relativeXPath":"/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"],"exampleValues":[{"num":0,"value":"\n \n \n "}],"unique_index":"1ri57q6vri5ljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":1,"contentType":0,"relative":false,"name":"参数2_链接文本","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":"新加坡"}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":false,"name":"参数3_链接地址","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":""}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":5,"index":10,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"//a[contains(., '东京')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[]}},{"id":6,"index":11,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":5,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}},{"id":-1,"index":12,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":6,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"ui-id-200\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[2]/li[27]/span[1]","//span[contains(., 'CNSHA上海')]","id(\"ui-id-200\")","//SPAN[@class='ui-menu-item-wrapper']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/16.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/16.json deleted file mode 100644 index 2be6021..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/16.json +++ /dev/null @@ -1 +0,0 @@ -{"id":16,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:47:58 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"$x('//*[@id=\"startportcod\"]')[0].value = \"CHSHA\";\n$x('//*[@id=\"endportcod\"]')[0].value = \"JPTYO\";","waitTime":0,"recordASField":0}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/17.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/17.json deleted file mode 100644 index 6be06cf..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/17.json +++ /dev/null @@ -1 +0,0 @@ -{"id":17,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:48:33 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"$x('//*[@id=\"startportcod\"]')[0].value = \"CHSHA\";\n$x('//*[@id=\"endportcod\"]')[0].value = \"JPTYO\";","waitTime":0,"recordASField":0}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/18.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/18.json deleted file mode 100644 index 8ceafab..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/18.json +++ /dev/null @@ -1 +0,0 @@ -{"id":18,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:48:33 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"$x('//*[@id=\"startportcod\"]')[0].value = \"CHSHA\";\n$x('//*[@id=\"endportcod\"]')[0].value = \"JPTYO\";","waitTime":0,"recordASField":0}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/19.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/19.json deleted file mode 100644 index 65df683..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/19.json +++ /dev/null @@ -1 +0,0 @@ -{"id":19,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:50:30 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":5,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"$x('//*[@id=\"startportcod\"]')[0].value = \"CHSHA\";\n$x('//*[@id=\"endportcod\"]')[0].value = \"JPTYO\";","waitTime":0,"recordASField":0}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/2.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/2.json deleted file mode 100644 index 9ea0372..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/2.json +++ /dev/null @@ -1 +0,0 @@ -{"id":2,"name":"新闻中心 - 小鱼易连-官网-让世界零距离","url":"https://www.xylink.com/news","links":"https://www.xylink.com/news","create_time":"6/27/2023, 1:44:49 AM","version":"0.3.2","containJudge":true,"desc":"https://www.xylink.com/news","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.xylink.com/news","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.xylink.com/news"}],"outputParameters":[{"id":0,"name":"参数2_文本","desc":"","type":"string","exampleValue":"亮相西部数博会,小鱼易连云视频助力数字经济高质量发展"}],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,8,12],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.xylink.com/news","links":"https://www.xylink.com/news","maxWaitTime":20,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":4,"index":2,"parentId":3,"type":1,"option":8,"title":"循环点击每个文章标题","sequence":[9,7,3,13,15],"isInLoop":true,"position":0,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":"2","pathList":"/html/body/div[1]/div/div[2]/section/div/div[2]/div/div[1]/div[2]/div[1]/div[1]\n/html/body/div[1]/div/div[2]/section/div/div[2]/div/div[2]/div[2]/div[1]/div[1]","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":3,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":""}},{"id":8,"index":3,"parentId":4,"type":0,"option":2,"title":"点击标题进详情页","sequence":[],"isInLoop":true,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":true,"xpath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[1]","wait":10,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":"","loopType":1}},{"id":-1,"index":4,"parentId":6,"type":1,"option":8,"title":"循环","sequence":[5],"isInLoop":true,"position":1,"parameters":{"history":5,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":1,"pathList":"","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":["/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[1]","//div[contains(., '亮相西部数博会,小鱼')]","//DIV[@class='xyEditor__index_title']"]}},{"id":-1,"index":5,"parentId":11,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":5,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":true,"name":"参数1_文本","desc":"","extractType":0,"relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"亮相西部数博会,小鱼易连云视频助力数字经济高质量发展"},{"num":1,"value":"2023-06-20    小鱼易连"},{"num":2,"value":"6月16-18日,由西安市人民政府、陕西省工业和信息化厅、陕西省互联网信息办公室、陕西省科学技术厅、陕西省通信管理局主办,以“数字创享 原启未来”为主题的第四届西部数字经济博览会(以下简称西部数博会)在陕西西安举办,活动重点展示陕西深入实施创新驱动发展战略成果,充分发挥深化西部数实深度融合发展的桥梁作用,推进西部数字经济高质量发展。\n \n\n\n\n \n小鱼易连携安全可信云视频,亮相中国电子云-中国信创云主题展区,与阿里巴巴、中软国际、太极股份、科大讯飞、东软集团、商汤科技、新华三等300余家数字化领域头部企业,共同展示数字创新成果,分享“数实融合”经验,以创新合力共同助力数字政府、智慧政法、央国企数字化、智慧金融、智慧教育、智慧医疗建设,促进数字经济高质量发展。\n \n\n数字创享 原启未来\n小鱼易连信创云视频筑牢数字底座\n\n \n\n党的二十大报告提出要“加快发展数字经济,促进数字经济和实体经济深度融合,打造具有国际竞争力的数字产业集群”。\n \n西部数博会以“数字创享 原启未来”为主题,旨在全面推动西部地区数字经济与实体经济深度融合。作为迄今为止西北地区最大的数字主题盛会,西部数博会搭建起西部数字经济创新发展、产业融合、交流合作的综合平台,成为搭建数字头部企业合作桥梁、引领数字经济发展的标志性盛会,也成为推进数字经济高质量发展的新引擎。\n \n小鱼易连以安全可信的自主技术,通过SVC+AVC双引擎和虚拟化部署架构,打造“云视频平台+云视频终端+开发平台”的信创解决方案,并满足对主流国产处理器、国产操作系统、国产数据库的全兼容,实现方案对各行各业场景的广泛适配和深入融合,期望以安全、创新的信创云视频驱动产业数字化和数字产业化发展。\n \n活动现场,小鱼易连面向领导嘉宾展示了“高安全·超融合·全连接”的云视频整体解决方案,一体化的云视频终端、4K专业智能终端以及能适用于大中小型会议室的全场景终端,能够为各类会议室、室内外的多场景,提供安全、稳定、高品质的视频应用和便捷协作,小鱼易连的系列产品获得了诸多领导嘉宾的好评和肯定。\n\n \n\n\n\n \n\n聚焦场景 数实融合\n云视频促进数字经济高质量发展\n\n \n\n随着“数实融合”不断加快场景创新、渗透应用、优化迭代,其催生的新模式、新业态将激活经济潜能,助力数字经济高质量发展。\n \n小鱼易连用云视频逐渐弥合“数字鸿沟”,基于中国电子PKS体系,构建PKSV可信云视频平台,深度融合视频会议、直播、点播、语音、监控等视讯功能,创新构建的会议会商、互联网+政务、协同办公、应急指挥、疫情防控、党建培训、远程教学、移动会议、执法巡查等应用,是“数实融合”深入发展的创新成果和必然结果,对高质量发展具有积极意义。\n \n在“数实融合”催生出的诸多云视频新场景赋能下,小鱼易连为政务、政法、企业、金融、教育、医疗等全行业数字化转型注入新活力。\n\n \n\n\n政务领域,云视频突破信息孤岛,实现省、市、县、乡、村多级可视化联动。\n\n\n政法领域,云视频深入业务全流程,提升司法行政效率和公共法律服务水平。\n\n\n企业领域,云视频融合央国企业务链路,助推跨级、跨部门协同高质效。\n\n\n金融行业,云视频全面适配行业场景,优化业务流程、加速数字化转型。\n\n\n教育行业,云视频为老师、学生构建沉浸式互动课堂,加速教育公平均衡。\n\n\n医疗领域,云视频为远程医疗提供支撑,促进分级诊疗、优化资源配置。\n\n\n \n\n\n\n \n\n数字化发展正加速向千行百业渗透,小鱼易连积极推动数字经济纵深发展。依托多年来的丰富积累和实践,小鱼易连已经为国家部委、政府机构和央国企等在内的各行各业16万家大中型客户提供服务,中华人民共和国水利部、国家税务总局、中华人民共和国审计署、广西壮族自治区人民政府、中国电子等应用云视频,开启全面的数字化转型和升级。\n蓬勃发展的数字经济已成为我国加快推进经济高质量发展的重要抓手,小鱼易连首当其冲,基于云视频的全栈资源、国产化平台、更优质的服务、更开放的生态,推动千行百业数字化,通过云视频对产业进行的全方位、全链条升级,充分激发数字技术对经济发展的倍增作用,从而为高质量发展提供有力支撑。\n"},{"num":3,"value":"Preview"}],"unique_index":"bxil6tnn2jlljd20x9i","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":11,"index":6,"parentId":7,"type":0,"option":2,"title":"点击下一页","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":5,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"ant-pagination-next\")]/button[1]","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[2]/ul[1]/li[7]/button[1]","//button[contains(., '')]","//BUTTON[@class='ant-pagination-item-link']"]}},{"id":7,"index":7,"parentId":4,"type":1,"option":8,"title":"While t_a < v_a","sequence":[6,10],"isInLoop":true,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":"5","pathList":"","textList":"","code":"return t_a < v_a","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0}},{"id":2,"index":8,"parentId":0,"type":0,"option":5,"title":"v_a = 0","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"v_a = 0;","waitTime":0,"recordASField":0}},{"id":6,"index":9,"parentId":4,"type":0,"option":5,"title":"t_a = 0","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"t_a = 0;","waitTime":0,"recordASField":0}},{"id":12,"index":10,"parentId":7,"type":0,"option":5,"title":"t_a = t_a + 1","sequence":[],"isInLoop":true,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"t_a = t_a + 1;","waitTime":0,"recordASField":0}},{"id":5,"index":11,"parentId":3,"type":0,"option":5,"title":"v_a = v_a + 1","sequence":[],"isInLoop":true,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"v_a = v_a + 1;","waitTime":0,"recordASField":0}},{"id":3,"index":12,"parentId":0,"type":1,"option":8,"title":"While v_a < 24","sequence":[2,11],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":"5","pathList":"","textList":"","code":"return v_a < 24;","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0}},{"id":9,"index":13,"parentId":4,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":3,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数2_文本","desc":"","relativeXPath":"/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[1]","allXPaths":["/html/body/div[1]/div[1]/div[2]/section[1]/div[1]/div[1]","//div[contains(., '亮相西部数博会,小鱼')]","//DIV[@class='xyEditor__index_title']"],"exampleValues":[{"num":0,"value":"亮相西部数博会,小鱼易连云视频助力数字经济高质量发展"}],"unique_index":"xuh40ko20yljd2j8fr","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":14,"index":14,"parentId":13,"type":0,"option":5,"title":"history.go(-1)","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"history.go(-1);","waitTime":0,"recordASField":0}},{"id":10,"index":15,"parentId":4,"type":2,"option":9,"title":"判断条件","sequence":[16],"isInLoop":true,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0}},{"id":13,"parentId":10,"index":16,"type":3,"option":10,"title":"IF v_a > 0","sequence":[14],"isInLoop":true,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"class":"5","value":"","code":"return v_a > 0;","waitTime":0},"position":0},{"id":-1,"parentId":10,"index":17,"type":3,"option":10,"title":"条件分支","sequence":[],"isInLoop":true,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"class":0,"value":"","code":"","waitTime":0},"position":1}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/20.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/20.json deleted file mode 100644 index a7ea171..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/20.json +++ /dev/null @@ -1 +0,0 @@ -{"id":20,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:51:31 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":10,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"$x('//*[@id=\"startportcod\"]')[0].value = \"CHSHA\";\n$x('//*[@id=\"endportcod\"]')[0].value = \"JPTYO\";","waitTime":0,"recordASField":0}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/21.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/21.json deleted file mode 100644 index 964d514..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/21.json +++ /dev/null @@ -1 +0,0 @@ -{"id":21,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:52:37 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,4,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":10,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"$x('//*[@id=\"startportcod\"]')[0].value = \"CHSHA\"","waitTime":0,"recordASField":0}},{"id":4,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}},{"id":3,"index":4,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"$x('//*[@id=\"endportcod\"]')[0].value = \"JPTYO\"","waitTime":0,"recordASField":0}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/22.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/22.json deleted file mode 100644 index a23a290..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/22.json +++ /dev/null @@ -1 +0,0 @@ -{"id":22,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:54:21 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,4,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":10,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"document.querySelector(\"#startportcod\").value = \"CHSHA\"","waitTime":0,"recordASField":0}},{"id":4,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}},{"id":3,"index":4,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"document.querySelector(\"#endportcod\").value = \"JPTYO\"","waitTime":0,"recordASField":0}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/23.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/23.json deleted file mode 100644 index 08727c6..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/23.json +++ /dev/null @@ -1 +0,0 @@ -{"id":23,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:54:21 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,4,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":10,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"document.querySelector(\"#startportcod\").value = \"CHSHA\"","waitTime":0,"recordASField":0}},{"id":4,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}},{"id":3,"index":4,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"document.querySelector(\"#endportcod\").value = \"JPTYO\"","waitTime":0,"recordASField":0}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/24.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/24.json deleted file mode 100644 index 306b433..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/24.json +++ /dev/null @@ -1 +0,0 @@ -{"id":24,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:54:21 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,4,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":10,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"document.querySelector(\"#startportcod\").value = \"CHSHA\"","waitTime":0,"recordASField":0}},{"id":4,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}},{"id":3,"index":4,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"document.querySelector(\"#endportcod\").value = \"JPTYO\"","waitTime":0,"recordASField":0}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/25.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/25.json deleted file mode 100644 index a4b5943..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/25.json +++ /dev/null @@ -1 +0,0 @@ -{"id":25,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:56:08 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,4,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":15,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"document.querySelector(\"#startportcod\").value = \"CHSHA\"","waitTime":0,"recordASField":0}},{"id":4,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}},{"id":3,"index":4,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"document.querySelector(\"#endportcod\").value = \"JPTYO\"","waitTime":0,"recordASField":0}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/26.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/26.json deleted file mode 100644 index ed11885..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/26.json +++ /dev/null @@ -1 +0,0 @@ -{"id":26,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:58:15 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":10,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":4,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"document.querySelector(\"#startportcod\").value = \"CNSHA\";\ndocument.querySelector(\"#endportcod\").value = \"JPTYO\";","waitTime":0,"recordASField":0}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}},{"id":-1,"index":4,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"","waitTime":0,"recordASField":0}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/27.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/27.json deleted file mode 100644 index 68d2145..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/27.json +++ /dev/null @@ -1 +0,0 @@ -{"id":27,"name":"Instant Price","url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","create_time":"6/27/2023, 6:02:55 PM","version":"0.3.2","containJudge":false,"desc":"https://www.maersk.com.cn/instantPrice/","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.maersk.com.cn/instantPrice/","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.maersk.com.cn/instantPrice/"},{"id":1,"name":"inputText_1","nodeName":"输入文字","nodeId":4,"desc":"要输入的文本,如京东搜索框输入:电脑","type":"string","exampleValue":"Shang","value":"Shang"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,5],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"shanghai","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":3,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":3,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"typeahead__suggestions__wrapper\")]/ul[1]/li[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/ul[1]/li[1]","//li[contains(., 'SHANGQIU (')]","//LI[@class='typeahead__suggestions__link typeahead__suggestions__link--history']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/28.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/28.json deleted file mode 100644 index 63a4e0e..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/28.json +++ /dev/null @@ -1 +0,0 @@ -{"id":28,"name":"Instant Price","url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","create_time":"6/27/2023, 6:02:55 PM","version":"0.3.2","containJudge":false,"desc":"https://www.maersk.com.cn/instantPrice/","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.maersk.com.cn/instantPrice/","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.maersk.com.cn/instantPrice/"},{"id":1,"name":"inputText_1","nodeName":"输入文字","nodeId":4,"desc":"要输入的文本,如京东搜索框输入:电脑","type":"string","exampleValue":"Shang","value":"Shang"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,5],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"shanghai","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":3,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":3,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"typeahead__suggestions__wrapper\")]/ul[1]/li[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/ul[1]/li[1]","//li[contains(., 'SHANGQIU (')]","//LI[@class='typeahead__suggestions__link typeahead__suggestions__link--history']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/29.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/29.json deleted file mode 100644 index 0732829..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/29.json +++ /dev/null @@ -1 +0,0 @@ -{"id":29,"name":"Instant Price","url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","create_time":"6/27/2023, 6:04:52 PM","version":"0.3.2","containJudge":false,"desc":"https://www.maersk.com.cn/instantPrice/","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.maersk.com.cn/instantPrice/","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.maersk.com.cn/instantPrice/"},{"id":1,"name":"inputText_1","nodeName":"输入文字","nodeId":4,"desc":"要输入的文本,如京东搜索框输入:电脑","type":"string","exampleValue":"Shang","value":"Shang"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,5],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"shanghai","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":3,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":6,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":3,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"typeahead__suggestions__wrapper\")]/ul[1]/li[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/ul[1]/li[1]","//li[contains(., 'SHANGQIU (')]","//LI[@class='typeahead__suggestions__link typeahead__suggestions__link--history']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/3.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/3.json deleted file mode 100644 index 9b15ee9..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/3.json +++ /dev/null @@ -1 +0,0 @@ -{"id":3,"name":"Artificial Intelligence authors/titles recent submissions","url":"https://arxiv.org/list/cs.AI/recent","links":"https://arxiv.org/list/cs.AI/recent","create_time":"6/27/2023, 2:39:57 AM","version":"0.3.2","containJudge":false,"desc":"https://arxiv.org/list/cs.AI/recent","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://arxiv.org/list/cs.AI/recent","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://arxiv.org/list/cs.AI/recent"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://arxiv.org/list/cs.AI/recent","links":"https://arxiv.org/list/cs.AI/recent","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":1,"option":8,"title":"循环","sequence":[3],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[4]/div[1]/dl[1]/dt/span[1]/a[2]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":1,"pathList":"","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":""}},{"id":3,"index":3,"parentId":2,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":4,"tabIndex":-1,"useLoop":true,"xpath":"/html/body/div[4]/div[1]/dl[1]/dt/span[1]/a[2]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":"","loopType":1}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/30.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/30.json deleted file mode 100644 index 0604625..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/30.json +++ /dev/null @@ -1 +0,0 @@ -{"id":30,"name":"Instant Price","url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","create_time":"6/27/2023, 6:06:01 PM","version":"0.3.2","containJudge":false,"desc":"https://www.maersk.com.cn/instantPrice/","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.maersk.com.cn/instantPrice/","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.maersk.com.cn/instantPrice/"},{"id":1,"name":"inputText_1","nodeName":"输入文字","nodeId":4,"desc":"要输入的文本,如京东搜索框输入:电脑","type":"string","exampleValue":"Shang","value":"Shang"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,5],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"shanghai","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":3,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":6,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":3,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//li[contains(., 'SHANGQIU (')]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/ul[1]/li[1]","//li[contains(., 'SHANGQIU (')]","//LI[@class='typeahead__suggestions__link typeahead__suggestions__link--history']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/31.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/31.json deleted file mode 100644 index d4c5aed..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/31.json +++ /dev/null @@ -1 +0,0 @@ -{"id":31,"name":"Instant Price","url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","create_time":"6/27/2023, 7:10:29 PM","version":"0.3.2","containJudge":false,"desc":"https://www.maersk.com.cn/instantPrice/","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.maersk.com.cn/instantPrice/","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.maersk.com.cn/instantPrice/"},{"id":1,"name":"inputText_1","nodeName":"输入文字","nodeId":4,"desc":"要输入的文本,如京东搜索框输入:电脑","type":"string","exampleValue":"Shang","value":"Shang"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,5],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"shanghai","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":3,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":6,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":3,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//li[contains(., 'SHANGQIU')]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/ul[1]/li[1]","//li[contains(., 'SHANGQIU (')]","//LI[@class='typeahead__suggestions__link typeahead__suggestions__link--history']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/32.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/32.json deleted file mode 100644 index aa1d241..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/32.json +++ /dev/null @@ -1 +0,0 @@ -{"id":32,"name":"Instant Price","url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","create_time":"6/27/2023, 7:25:30 PM","version":"0.3.2","containJudge":false,"desc":"https://www.maersk.com.cn/instantPrice/","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.maersk.com.cn/instantPrice/","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.maersk.com.cn/instantPrice/"},{"id":1,"name":"inputText_1","nodeName":"输入文字","nodeId":4,"desc":"要输入的文本,如京东搜索框输入:电脑","type":"string","exampleValue":"Shang","value":"Shang"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,5],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"shanghai","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":3,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":3,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//li[contains(., 'SHANGQIU')]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/ul[1]/li[1]","//li[contains(., 'SHANGQIU (')]","//LI[@class='typeahead__suggestions__link typeahead__suggestions__link--history']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/33.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/33.json deleted file mode 100644 index 5ed818a..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/33.json +++ /dev/null @@ -1 +0,0 @@ -{"id":33,"name":"Instant Price","url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","create_time":"6/27/2023, 7:25:30 PM","version":"0.3.2","containJudge":false,"desc":"https://www.maersk.com.cn/instantPrice/","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.maersk.com.cn/instantPrice/","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.maersk.com.cn/instantPrice/"},{"id":1,"name":"inputText_1","nodeName":"输入文字","nodeId":4,"desc":"要输入的文本,如京东搜索框输入:电脑","type":"string","exampleValue":"Shang","value":"Shang"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,5],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.maersk.com.cn/instantPrice/","links":"https://www.maersk.com.cn/instantPrice/","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"shanghai","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":3,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":3,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//li[contains(., 'SHANGQIU')]","wait":20,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/ul[1]/li[1]","//li[contains(., 'SHANGQIU (')]","//LI[@class='typeahead__suggestions__link typeahead__suggestions__link--history']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":4,"title":"输入文字","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":13,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"searchFormOrigin\")]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"value":"Shang","allXPaths":["/html/body/div[2]/main[1]/div[1]/article[1]/section[1]/section[1]/section[1]/div[1]/form[1]/fieldset[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/input[1]","//input[contains(., '')]","//INPUT[@class='form-input__field']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/34.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/34.json deleted file mode 100644 index 1bfdfae..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/34.json +++ /dev/null @@ -1 +0,0 @@ -{"id":34,"name":"京东全球版-专业的综合网上购物商城","url":"https://www.jd.com","links":"https://www.jd.com","create_time":"6/28/2023, 6:55:56 PM","version":"0.3.2","containJudge":false,"desc":"https://www.jd.com","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.jd.com","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.jd.com"}],"outputParameters":[{"id":0,"name":"参数1_链接文本","desc":"","type":"string","exampleValue":"手机"},{"id":1,"name":"参数2_链接地址","desc":"","type":"string","exampleValue":"https://shouji.jd.com/"}],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,4],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.jd.com","links":"https://www.jd.com","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":1,"option":8,"title":"循环","sequence":[3],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div/a","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":1,"pathList":"","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":["/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/a[1]","//a[contains(., '手机')]"]}},{"id":4,"index":3,"parentId":2,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":1,"contentType":0,"relative":true,"name":"参数1_链接文本","desc":"","extractType":0,"relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"手机"},{"num":1,"value":"数码"},{"num":2,"value":"家用电器"},{"num":3,"value":"电脑"},{"num":4,"value":"办公"},{"num":5,"value":"家纺"},{"num":6,"value":"家居"},{"num":7,"value":"厨具"},{"num":8,"value":"家具"},{"num":9,"value":"家装"},{"num":10,"value":"灯具"},{"num":11,"value":"工业品"},{"num":12,"value":"内衣"},{"num":13,"value":"男装"},{"num":14,"value":"女装"},{"num":15,"value":"童装"},{"num":16,"value":"箱包"},{"num":17,"value":"钟表"},{"num":18,"value":"珠宝"},{"num":19,"value":"女鞋"},{"num":20,"value":"运动"},{"num":21,"value":"户外"},{"num":22,"value":"男鞋"},{"num":23,"value":"汽车用品"},{"num":24,"value":"车载电器"},{"num":25,"value":"母婴"},{"num":26,"value":"洗护喂养"},{"num":27,"value":"玩具乐器"},{"num":28,"value":"宠物生活"},{"num":29,"value":"家庭清洁"},{"num":30,"value":"个人护理"},{"num":31,"value":"计生情趣"},{"num":32,"value":"图书"},{"num":33,"value":"童书"},{"num":34,"value":"文学"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":true,"name":"参数2_链接地址","desc":"","relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"https://shouji.jd.com/"},{"num":1,"value":"https://shuma.jd.com/"},{"num":2,"value":"https://search.jd.com/Search?keyword=%E5%B0%8F%E5%AE%B6%E7%94%B5&enc=utf-8&wq=%E5%B0%8F%E5%AE%B6%E7%94%B5&pvid=261a350161304c979fa0e7ce95c05671"},{"num":3,"value":"https://diannao.jd.com/"},{"num":4,"value":"https://bg.jd.com/"},{"num":5,"value":"https://channel.jd.com/jf.html"},{"num":6,"value":"https://channel.jd.com/home.html"},{"num":7,"value":"https://channel.jd.com/kitchenware.html"},{"num":8,"value":"https://channel.jd.com/furniture.html"},{"num":9,"value":"https://jzjc.jd.com/"},{"num":10,"value":"https://channel.jd.com/9855-9856.html"},{"num":11,"value":"https://pro.jd.com/mall/active/2u2DR1dUiK34csAE3DqmcG8aXvUK/index.html"},{"num":12,"value":"https://channel.jd.com/underwear.html"},{"num":13,"value":"https://channel.jd.com/1315-1342.html"},{"num":14,"value":"https://channel.jd.com/women.html"},{"num":15,"value":"https://list.jd.com/list.html?cat=1319,11842"},{"num":16,"value":"https://channel.jd.com/bag.html"},{"num":17,"value":"https://channel.jd.com/watch.html"},{"num":18,"value":"https://channel.jd.com/jewellery.html"},{"num":19,"value":"https://channel.jd.com/womensshoes.html"},{"num":20,"value":"https://phat.jd.com/10-109.html"},{"num":21,"value":"https://channel.jd.com/outdoor.html"},{"num":22,"value":"https://channel.jd.com/mensshoes.html"},{"num":23,"value":"https://che.jd.com/"},{"num":24,"value":"https://list.jd.com/list.html?cat=6728,6740&page=1&delivery_glb=1&stock=1&sort=sort_totalsales15_desc&trans=1&JL=4_7_0#J_main"},{"num":25,"value":"https://search.jd.com/Search?keyword=%E6%AF%8D%E5%A9%B4&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%AF%8D%E5%A9%B4&stock=1&gp=2&click=1"},{"num":26,"value":"https://channel.jd.com/feed.html"},{"num":27,"value":"https://toy.jd.com/"},{"num":28,"value":"https://channel.jd.com/pet.html"},{"num":29,"value":"https://channel.jd.com/beauty.html"},{"num":30,"value":"https://lady.jd.com/"},{"num":31,"value":"https://channel.jd.com/9192-9196.html"},{"num":32,"value":"https://book.jd.com/"},{"num":33,"value":"https://book.jd.com/children.html"},{"num":34,"value":"https://channel.jd.com/p_wenxuezongheguan.html"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}],"loopType":1}},{"id":3,"index":4,"parentId":0,"type":0,"option":5,"title":"参数1_链接文本","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"return \"\"","waitTime":0,"recordASField":0}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/35.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/35.json deleted file mode 100644 index 624ec9f..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/35.json +++ /dev/null @@ -1 +0,0 @@ -{"id":35,"name":"京东全球版-专业的综合网上购物商城","url":"https://www.jd.com","links":"https://www.jd.com","create_time":"6/28/2023, 6:59:30 PM","version":"0.3.2","containJudge":false,"desc":"https://www.jd.com","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.jd.com","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.jd.com"}],"outputParameters":[{"id":0,"name":"参数1_链接文本","desc":"","type":"string","exampleValue":"手机"},{"id":1,"name":"参数2_链接地址","desc":"","type":"string","exampleValue":"https://shouji.jd.com/"},{"id":2,"name":"参数1_链接文本","desc":"自定义操作返回的数据","type":"string","exampleValue":""}],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,4],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.jd.com","links":"https://www.jd.com","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":1,"option":8,"title":"循环","sequence":[3],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div/a","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":1,"pathList":"","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":["/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/a[1]","//a[contains(., '手机')]"]}},{"id":4,"index":3,"parentId":2,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":1,"contentType":0,"relative":true,"name":"参数1_链接文本","desc":"","extractType":0,"relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"手机"},{"num":1,"value":"数码"},{"num":2,"value":"家用电器"},{"num":3,"value":"电脑"},{"num":4,"value":"办公"},{"num":5,"value":"家纺"},{"num":6,"value":"家居"},{"num":7,"value":"厨具"},{"num":8,"value":"家具"},{"num":9,"value":"家装"},{"num":10,"value":"灯具"},{"num":11,"value":"工业品"},{"num":12,"value":"内衣"},{"num":13,"value":"男装"},{"num":14,"value":"女装"},{"num":15,"value":"童装"},{"num":16,"value":"箱包"},{"num":17,"value":"钟表"},{"num":18,"value":"珠宝"},{"num":19,"value":"女鞋"},{"num":20,"value":"运动"},{"num":21,"value":"户外"},{"num":22,"value":"男鞋"},{"num":23,"value":"汽车用品"},{"num":24,"value":"车载电器"},{"num":25,"value":"母婴"},{"num":26,"value":"洗护喂养"},{"num":27,"value":"玩具乐器"},{"num":28,"value":"宠物生活"},{"num":29,"value":"家庭清洁"},{"num":30,"value":"个人护理"},{"num":31,"value":"计生情趣"},{"num":32,"value":"图书"},{"num":33,"value":"童书"},{"num":34,"value":"文学"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":true,"name":"参数2_链接地址","desc":"","relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"https://shouji.jd.com/"},{"num":1,"value":"https://shuma.jd.com/"},{"num":2,"value":"https://search.jd.com/Search?keyword=%E5%B0%8F%E5%AE%B6%E7%94%B5&enc=utf-8&wq=%E5%B0%8F%E5%AE%B6%E7%94%B5&pvid=261a350161304c979fa0e7ce95c05671"},{"num":3,"value":"https://diannao.jd.com/"},{"num":4,"value":"https://bg.jd.com/"},{"num":5,"value":"https://channel.jd.com/jf.html"},{"num":6,"value":"https://channel.jd.com/home.html"},{"num":7,"value":"https://channel.jd.com/kitchenware.html"},{"num":8,"value":"https://channel.jd.com/furniture.html"},{"num":9,"value":"https://jzjc.jd.com/"},{"num":10,"value":"https://channel.jd.com/9855-9856.html"},{"num":11,"value":"https://pro.jd.com/mall/active/2u2DR1dUiK34csAE3DqmcG8aXvUK/index.html"},{"num":12,"value":"https://channel.jd.com/underwear.html"},{"num":13,"value":"https://channel.jd.com/1315-1342.html"},{"num":14,"value":"https://channel.jd.com/women.html"},{"num":15,"value":"https://list.jd.com/list.html?cat=1319,11842"},{"num":16,"value":"https://channel.jd.com/bag.html"},{"num":17,"value":"https://channel.jd.com/watch.html"},{"num":18,"value":"https://channel.jd.com/jewellery.html"},{"num":19,"value":"https://channel.jd.com/womensshoes.html"},{"num":20,"value":"https://phat.jd.com/10-109.html"},{"num":21,"value":"https://channel.jd.com/outdoor.html"},{"num":22,"value":"https://channel.jd.com/mensshoes.html"},{"num":23,"value":"https://che.jd.com/"},{"num":24,"value":"https://list.jd.com/list.html?cat=6728,6740&page=1&delivery_glb=1&stock=1&sort=sort_totalsales15_desc&trans=1&JL=4_7_0#J_main"},{"num":25,"value":"https://search.jd.com/Search?keyword=%E6%AF%8D%E5%A9%B4&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%AF%8D%E5%A9%B4&stock=1&gp=2&click=1"},{"num":26,"value":"https://channel.jd.com/feed.html"},{"num":27,"value":"https://toy.jd.com/"},{"num":28,"value":"https://channel.jd.com/pet.html"},{"num":29,"value":"https://channel.jd.com/beauty.html"},{"num":30,"value":"https://lady.jd.com/"},{"num":31,"value":"https://channel.jd.com/9192-9196.html"},{"num":32,"value":"https://book.jd.com/"},{"num":33,"value":"https://book.jd.com/children.html"},{"num":34,"value":"https://channel.jd.com/p_wenxuezongheguan.html"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}],"loopType":1}},{"id":3,"index":4,"parentId":0,"type":0,"option":5,"title":"参数1_链接文本","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"return \"\"","waitTime":0,"recordASField":"1"}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/36.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/36.json deleted file mode 100644 index 6199d34..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/36.json +++ /dev/null @@ -1 +0,0 @@ -{"id":36,"name":"京东全球版-专业的综合网上购物商城","url":"https://www.jd.com","links":"https://www.jd.com","create_time":"6/28/2023, 6:59:30 PM","version":"0.3.2","containJudge":false,"desc":"https://www.jd.com","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.jd.com","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.jd.com"}],"outputParameters":[{"id":0,"name":"参数1_链接文本","desc":"","type":"string","exampleValue":"手机"},{"id":1,"name":"参数2_链接地址","desc":"","type":"string","exampleValue":"https://shouji.jd.com/"},{"id":2,"name":"参数1_链接文本","desc":"自定义操作返回的数据","type":"string","exampleValue":""}],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,4],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.jd.com","links":"https://www.jd.com","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":1,"option":8,"title":"循环","sequence":[3],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div/a","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":1,"pathList":"","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":["/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/a[1]","//a[contains(., '手机')]"]}},{"id":4,"index":3,"parentId":2,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":1,"contentType":0,"relative":true,"name":"参数1_链接文本","desc":"","extractType":0,"relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"手机"},{"num":1,"value":"数码"},{"num":2,"value":"家用电器"},{"num":3,"value":"电脑"},{"num":4,"value":"办公"},{"num":5,"value":"家纺"},{"num":6,"value":"家居"},{"num":7,"value":"厨具"},{"num":8,"value":"家具"},{"num":9,"value":"家装"},{"num":10,"value":"灯具"},{"num":11,"value":"工业品"},{"num":12,"value":"内衣"},{"num":13,"value":"男装"},{"num":14,"value":"女装"},{"num":15,"value":"童装"},{"num":16,"value":"箱包"},{"num":17,"value":"钟表"},{"num":18,"value":"珠宝"},{"num":19,"value":"女鞋"},{"num":20,"value":"运动"},{"num":21,"value":"户外"},{"num":22,"value":"男鞋"},{"num":23,"value":"汽车用品"},{"num":24,"value":"车载电器"},{"num":25,"value":"母婴"},{"num":26,"value":"洗护喂养"},{"num":27,"value":"玩具乐器"},{"num":28,"value":"宠物生活"},{"num":29,"value":"家庭清洁"},{"num":30,"value":"个人护理"},{"num":31,"value":"计生情趣"},{"num":32,"value":"图书"},{"num":33,"value":"童书"},{"num":34,"value":"文学"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":true,"name":"参数2_链接地址","desc":"","relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"https://shouji.jd.com/"},{"num":1,"value":"https://shuma.jd.com/"},{"num":2,"value":"https://search.jd.com/Search?keyword=%E5%B0%8F%E5%AE%B6%E7%94%B5&enc=utf-8&wq=%E5%B0%8F%E5%AE%B6%E7%94%B5&pvid=261a350161304c979fa0e7ce95c05671"},{"num":3,"value":"https://diannao.jd.com/"},{"num":4,"value":"https://bg.jd.com/"},{"num":5,"value":"https://channel.jd.com/jf.html"},{"num":6,"value":"https://channel.jd.com/home.html"},{"num":7,"value":"https://channel.jd.com/kitchenware.html"},{"num":8,"value":"https://channel.jd.com/furniture.html"},{"num":9,"value":"https://jzjc.jd.com/"},{"num":10,"value":"https://channel.jd.com/9855-9856.html"},{"num":11,"value":"https://pro.jd.com/mall/active/2u2DR1dUiK34csAE3DqmcG8aXvUK/index.html"},{"num":12,"value":"https://channel.jd.com/underwear.html"},{"num":13,"value":"https://channel.jd.com/1315-1342.html"},{"num":14,"value":"https://channel.jd.com/women.html"},{"num":15,"value":"https://list.jd.com/list.html?cat=1319,11842"},{"num":16,"value":"https://channel.jd.com/bag.html"},{"num":17,"value":"https://channel.jd.com/watch.html"},{"num":18,"value":"https://channel.jd.com/jewellery.html"},{"num":19,"value":"https://channel.jd.com/womensshoes.html"},{"num":20,"value":"https://phat.jd.com/10-109.html"},{"num":21,"value":"https://channel.jd.com/outdoor.html"},{"num":22,"value":"https://channel.jd.com/mensshoes.html"},{"num":23,"value":"https://che.jd.com/"},{"num":24,"value":"https://list.jd.com/list.html?cat=6728,6740&page=1&delivery_glb=1&stock=1&sort=sort_totalsales15_desc&trans=1&JL=4_7_0#J_main"},{"num":25,"value":"https://search.jd.com/Search?keyword=%E6%AF%8D%E5%A9%B4&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%AF%8D%E5%A9%B4&stock=1&gp=2&click=1"},{"num":26,"value":"https://channel.jd.com/feed.html"},{"num":27,"value":"https://toy.jd.com/"},{"num":28,"value":"https://channel.jd.com/pet.html"},{"num":29,"value":"https://channel.jd.com/beauty.html"},{"num":30,"value":"https://lady.jd.com/"},{"num":31,"value":"https://channel.jd.com/9192-9196.html"},{"num":32,"value":"https://book.jd.com/"},{"num":33,"value":"https://book.jd.com/children.html"},{"num":34,"value":"https://channel.jd.com/p_wenxuezongheguan.html"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}],"loopType":1}},{"id":3,"index":4,"parentId":0,"type":0,"option":5,"title":"参数1_链接文本","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"return \"\"","waitTime":0,"recordASField":"1"}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/4.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/4.json deleted file mode 100644 index cc20056..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/4.json +++ /dev/null @@ -1 +0,0 @@ -{"id":4,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 1:15:48 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":2,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"ui-id-76\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/5.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/5.json deleted file mode 100644 index 560ba6b..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/5.json +++ /dev/null @@ -1 +0,0 @@ -{"id":5,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 1:16:57 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"ui-id-76\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/6.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/6.json deleted file mode 100644 index 72c18af..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/6.json +++ /dev/null @@ -1 +0,0 @@ -{"id":6,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 1:18:09 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//span[contains(., 'CNWEI威海')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/7.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/7.json deleted file mode 100644 index 8c6d869..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/7.json +++ /dev/null @@ -1 +0,0 @@ -{"id":7,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 1:22:50 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3,8,10,11],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//span[contains(., '上海')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":4,"index":8,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":9,"parentId":0,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数1_文本","desc":"","relativeXPath":"/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"],"exampleValues":[{"num":0,"value":"\n \n \n "}],"unique_index":"1ri57q6vri5ljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":1,"contentType":0,"relative":false,"name":"参数2_链接文本","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":"新加坡"}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":false,"name":"参数3_链接地址","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":""}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":5,"index":10,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"//a[contains(., '东京')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[]}},{"id":6,"index":11,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":5,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/8.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/8.json deleted file mode 100644 index 0aa1c42..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/8.json +++ /dev/null @@ -1 +0,0 @@ -{"id":8,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:26:13 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3,8,10,11],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//span[contains(., 'CHSHA')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":4,"index":8,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":9,"parentId":0,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数1_文本","desc":"","relativeXPath":"/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"],"exampleValues":[{"num":0,"value":"\n \n \n "}],"unique_index":"1ri57q6vri5ljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":1,"contentType":0,"relative":false,"name":"参数2_链接文本","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":"新加坡"}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":false,"name":"参数3_链接地址","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":""}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":5,"index":10,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"//a[contains(., 'JPTYO')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[]}},{"id":6,"index":11,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":5,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/execution_instances/9.json b/.temp_to_pub/EasySpider_windows_x64/execution_instances/9.json deleted file mode 100644 index 31d0e4a..0000000 --- a/.temp_to_pub/EasySpider_windows_x64/execution_instances/9.json +++ /dev/null @@ -1 +0,0 @@ -{"id":9,"name":"锦江航运","url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","create_time":"6/27/2023, 2:26:13 PM","version":"0.3.2","containJudge":false,"desc":"https://ejj.jjshipping.cn/home","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://ejj.jjshipping.cn/home","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://ejj.jjshipping.cn/home"}],"outputParameters":[],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,3,8,10,11],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://ejj.jjshipping.cn/home","links":"https://ejj.jjshipping.cn/home","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":3,"index":3,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//span[contains(., 'CHSHA')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/ul[1]/li[5]/span[1]","//span[contains(., 'CNWEI威海')]","id(\"ui-id-76\")","//SPAN[@class='ui-menu-item-wrapper']"]}},{"id":2,"index":4,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":5,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":6,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":7,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"select-wrap\")]/label[1]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[1]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":4,"index":8,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":3,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"//*[contains(@class, \"pl60\")]/div[1]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"]}},{"id":-1,"index":9,"parentId":0,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":3,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":0,"contentType":0,"relative":false,"name":"参数1_文本","desc":"","relativeXPath":"/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","allXPaths":["/html/body/div[4]/div[1]/div[1]/label[2]/div[1]","//div[contains(., '')]","//DIV[@class='selectedrow']"],"exampleValues":[{"num":0,"value":"\n \n \n "}],"unique_index":"1ri57q6vri5ljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":1,"contentType":0,"relative":false,"name":"参数2_链接文本","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":"新加坡"}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":false,"name":"参数3_链接地址","desc":"","relativeXPath":"/html/body/ul[2]/li[4]/span[1]/a[2]","allXPaths":["/html/body/ul[2]/li[4]/span[1]/a[2]","//a[contains(., '新加坡')]","//A[@class='rightlabel']"],"exampleValues":[{"num":0,"value":""}],"unique_index":"ws9b52fuzeljduap98","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}]}},{"id":5,"index":10,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":4,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"//a[contains(., 'JPTYO')]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[]}},{"id":6,"index":11,"parentId":0,"type":0,"option":2,"title":"点击元素","sequence":[],"isInLoop":false,"position":5,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"//*[@id=\"queryfee\"]","wait":2,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"maxWaitTime":10,"paras":[],"allXPaths":["/html/body/div[4]/div[1]/div[1]/div[2]/a[1]","//a[contains(., '查询运费')]","id(\"queryfee\")","//A[@class='btn btn-search']"]}}]} \ No newline at end of file diff --git a/.temp_to_pub/EasySpider_windows_x64/tasks/47.json b/.temp_to_pub/EasySpider_windows_x64/tasks/47.json index ad02e70..0793866 100644 --- a/.temp_to_pub/EasySpider_windows_x64/tasks/47.json +++ b/.temp_to_pub/EasySpider_windows_x64/tasks/47.json @@ -1 +1 @@ -{"id":47,"name":"京东全球版-专业的综合网上购物商城","url":"https://www.jd.com","links":"https://www.jd.com","create_time":"6/28/2023, 6:59:30 PM","version":"0.3.2","containJudge":false,"desc":"https://www.jd.com","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.jd.com","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.jd.com"}],"outputParameters":[{"id":0,"name":"参数1_链接文本","desc":"","type":"string","exampleValue":"手机"},{"id":1,"name":"参数2_链接地址","desc":"","type":"string","exampleValue":"https://shouji.jd.com/"},{"id":2,"name":"参数1_链接文本","desc":"自定义操作返回的数据","type":"string","exampleValue":""}],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,2,4],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.jd.com","links":"https://www.jd.com","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":2,"index":2,"parentId":0,"type":1,"option":8,"title":"循环","sequence":[3],"isInLoop":false,"position":1,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div/a","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":1,"pathList":"","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":["/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/a[1]","//a[contains(., '手机')]"]}},{"id":4,"index":3,"parentId":2,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":1,"contentType":0,"relative":true,"name":"参数1_链接文本","desc":"","extractType":0,"relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"手机"},{"num":1,"value":"数码"},{"num":2,"value":"家用电器"},{"num":3,"value":"电脑"},{"num":4,"value":"办公"},{"num":5,"value":"家纺"},{"num":6,"value":"家居"},{"num":7,"value":"厨具"},{"num":8,"value":"家具"},{"num":9,"value":"家装"},{"num":10,"value":"灯具"},{"num":11,"value":"工业品"},{"num":12,"value":"内衣"},{"num":13,"value":"男装"},{"num":14,"value":"女装"},{"num":15,"value":"童装"},{"num":16,"value":"箱包"},{"num":17,"value":"钟表"},{"num":18,"value":"珠宝"},{"num":19,"value":"女鞋"},{"num":20,"value":"运动"},{"num":21,"value":"户外"},{"num":22,"value":"男鞋"},{"num":23,"value":"汽车用品"},{"num":24,"value":"车载电器"},{"num":25,"value":"母婴"},{"num":26,"value":"洗护喂养"},{"num":27,"value":"玩具乐器"},{"num":28,"value":"宠物生活"},{"num":29,"value":"家庭清洁"},{"num":30,"value":"个人护理"},{"num":31,"value":"计生情趣"},{"num":32,"value":"图书"},{"num":33,"value":"童书"},{"num":34,"value":"文学"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":true,"name":"参数2_链接地址","desc":"","relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"https://shouji.jd.com/"},{"num":1,"value":"https://shuma.jd.com/"},{"num":2,"value":"https://search.jd.com/Search?keyword=%E5%B0%8F%E5%AE%B6%E7%94%B5&enc=utf-8&wq=%E5%B0%8F%E5%AE%B6%E7%94%B5&pvid=261a350161304c979fa0e7ce95c05671"},{"num":3,"value":"https://diannao.jd.com/"},{"num":4,"value":"https://bg.jd.com/"},{"num":5,"value":"https://channel.jd.com/jf.html"},{"num":6,"value":"https://channel.jd.com/home.html"},{"num":7,"value":"https://channel.jd.com/kitchenware.html"},{"num":8,"value":"https://channel.jd.com/furniture.html"},{"num":9,"value":"https://jzjc.jd.com/"},{"num":10,"value":"https://channel.jd.com/9855-9856.html"},{"num":11,"value":"https://pro.jd.com/mall/active/2u2DR1dUiK34csAE3DqmcG8aXvUK/index.html"},{"num":12,"value":"https://channel.jd.com/underwear.html"},{"num":13,"value":"https://channel.jd.com/1315-1342.html"},{"num":14,"value":"https://channel.jd.com/women.html"},{"num":15,"value":"https://list.jd.com/list.html?cat=1319,11842"},{"num":16,"value":"https://channel.jd.com/bag.html"},{"num":17,"value":"https://channel.jd.com/watch.html"},{"num":18,"value":"https://channel.jd.com/jewellery.html"},{"num":19,"value":"https://channel.jd.com/womensshoes.html"},{"num":20,"value":"https://phat.jd.com/10-109.html"},{"num":21,"value":"https://channel.jd.com/outdoor.html"},{"num":22,"value":"https://channel.jd.com/mensshoes.html"},{"num":23,"value":"https://che.jd.com/"},{"num":24,"value":"https://list.jd.com/list.html?cat=6728,6740&page=1&delivery_glb=1&stock=1&sort=sort_totalsales15_desc&trans=1&JL=4_7_0#J_main"},{"num":25,"value":"https://search.jd.com/Search?keyword=%E6%AF%8D%E5%A9%B4&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%AF%8D%E5%A9%B4&stock=1&gp=2&click=1"},{"num":26,"value":"https://channel.jd.com/feed.html"},{"num":27,"value":"https://toy.jd.com/"},{"num":28,"value":"https://channel.jd.com/pet.html"},{"num":29,"value":"https://channel.jd.com/beauty.html"},{"num":30,"value":"https://lady.jd.com/"},{"num":31,"value":"https://channel.jd.com/9192-9196.html"},{"num":32,"value":"https://book.jd.com/"},{"num":33,"value":"https://book.jd.com/children.html"},{"num":34,"value":"https://channel.jd.com/p_wenxuezongheguan.html"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}],"loopType":1}},{"id":3,"index":4,"parentId":0,"type":0,"option":5,"title":"参数1_链接文本","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"return \"\"","waitTime":0,"recordASField":"1"}}]} \ No newline at end of file +{"id":47,"name":"京东全球版-专业的综合网上购物商城","url":"https://www.jd.com","links":"https://www.jd.com","create_time":"6/30/2023, 8:21:24 PM","version":"0.3.2","containJudge":false,"desc":"https://www.jd.com","inputParameters":[{"id":0,"name":"urlList_0","nodeId":1,"nodeName":"打开网页","value":"https://www.jd.com","desc":"要采集的网址列表,多行以\\n分开","type":"string","exampleValue":"https://www.jd.com"}],"outputParameters":[{"id":0,"name":"参数1_链接文本","desc":"自定义操作返回的数据","type":"string","exampleValue":""},{"id":1,"name":"自定义操作","desc":"自定义操作返回的数据","type":"string","exampleValue":""}],"graph":[{"index":0,"id":0,"parentId":0,"type":-1,"option":0,"title":"root","sequence":[1,4,5],"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0},"isInLoop":false},{"id":1,"index":1,"parentId":0,"type":0,"option":1,"title":"打开网页","sequence":[],"isInLoop":false,"position":0,"parameters":{"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"url":"https://www.jd.com","links":"https://www.jd.com","maxWaitTime":10,"scrollType":0,"scrollCount":1,"scrollWaitTime":1}},{"id":-1,"index":2,"parentId":0,"type":1,"option":8,"title":"循环","sequence":[3],"isInLoop":false,"position":2,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div/a","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"scrollType":0,"scrollCount":1,"scrollWaitTime":1,"loopType":1,"pathList":"","textList":"","code":"","waitTime":0,"exitCount":0,"historyWait":2,"breakMode":0,"breakCode":"","breakCodeWaitTime":0,"allXPaths":["/html/body/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/a[1]","//a[contains(., '手机')]"]}},{"id":-1,"index":3,"parentId":3,"type":0,"option":3,"title":"提取数据","sequence":[],"isInLoop":true,"position":0,"parameters":{"history":4,"tabIndex":-1,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"paras":[{"nodeType":1,"contentType":0,"relative":true,"name":"参数1_链接文本","desc":"","extractType":0,"relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"手机"},{"num":1,"value":"数码"},{"num":2,"value":"家用电器"},{"num":3,"value":"电脑"},{"num":4,"value":"办公"},{"num":5,"value":"家纺"},{"num":6,"value":"家居"},{"num":7,"value":"厨具"},{"num":8,"value":"家具"},{"num":9,"value":"家装"},{"num":10,"value":"灯具"},{"num":11,"value":"工业品"},{"num":12,"value":"内衣"},{"num":13,"value":"男装"},{"num":14,"value":"女装"},{"num":15,"value":"童装"},{"num":16,"value":"箱包"},{"num":17,"value":"钟表"},{"num":18,"value":"珠宝"},{"num":19,"value":"女鞋"},{"num":20,"value":"运动"},{"num":21,"value":"户外"},{"num":22,"value":"男鞋"},{"num":23,"value":"汽车用品"},{"num":24,"value":"车载电器"},{"num":25,"value":"母婴"},{"num":26,"value":"洗护喂养"},{"num":27,"value":"玩具乐器"},{"num":28,"value":"宠物生活"},{"num":29,"value":"家庭清洁"},{"num":30,"value":"个人护理"},{"num":31,"value":"计生情趣"},{"num":32,"value":"图书"},{"num":33,"value":"童书"},{"num":34,"value":"文学"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0},{"nodeType":2,"contentType":0,"relative":true,"name":"参数2_链接地址","desc":"","relativeXPath":"","allXPaths":"","exampleValues":[{"num":0,"value":"https://shouji.jd.com/"},{"num":1,"value":"https://shuma.jd.com/"},{"num":2,"value":"https://search.jd.com/Search?keyword=%E5%B0%8F%E5%AE%B6%E7%94%B5&enc=utf-8&wq=%E5%B0%8F%E5%AE%B6%E7%94%B5&pvid=261a350161304c979fa0e7ce95c05671"},{"num":3,"value":"https://diannao.jd.com/"},{"num":4,"value":"https://bg.jd.com/"},{"num":5,"value":"https://channel.jd.com/jf.html"},{"num":6,"value":"https://channel.jd.com/home.html"},{"num":7,"value":"https://channel.jd.com/kitchenware.html"},{"num":8,"value":"https://channel.jd.com/furniture.html"},{"num":9,"value":"https://jzjc.jd.com/"},{"num":10,"value":"https://channel.jd.com/9855-9856.html"},{"num":11,"value":"https://pro.jd.com/mall/active/2u2DR1dUiK34csAE3DqmcG8aXvUK/index.html"},{"num":12,"value":"https://channel.jd.com/underwear.html"},{"num":13,"value":"https://channel.jd.com/1315-1342.html"},{"num":14,"value":"https://channel.jd.com/women.html"},{"num":15,"value":"https://list.jd.com/list.html?cat=1319,11842"},{"num":16,"value":"https://channel.jd.com/bag.html"},{"num":17,"value":"https://channel.jd.com/watch.html"},{"num":18,"value":"https://channel.jd.com/jewellery.html"},{"num":19,"value":"https://channel.jd.com/womensshoes.html"},{"num":20,"value":"https://phat.jd.com/10-109.html"},{"num":21,"value":"https://channel.jd.com/outdoor.html"},{"num":22,"value":"https://channel.jd.com/mensshoes.html"},{"num":23,"value":"https://che.jd.com/"},{"num":24,"value":"https://list.jd.com/list.html?cat=6728,6740&page=1&delivery_glb=1&stock=1&sort=sort_totalsales15_desc&trans=1&JL=4_7_0#J_main"},{"num":25,"value":"https://search.jd.com/Search?keyword=%E6%AF%8D%E5%A9%B4&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%AF%8D%E5%A9%B4&stock=1&gp=2&click=1"},{"num":26,"value":"https://channel.jd.com/feed.html"},{"num":27,"value":"https://toy.jd.com/"},{"num":28,"value":"https://channel.jd.com/pet.html"},{"num":29,"value":"https://channel.jd.com/beauty.html"},{"num":30,"value":"https://lady.jd.com/"},{"num":31,"value":"https://channel.jd.com/9192-9196.html"},{"num":32,"value":"https://book.jd.com/"},{"num":33,"value":"https://book.jd.com/children.html"},{"num":34,"value":"https://channel.jd.com/p_wenxuezongheguan.html"}],"unique_index":"2fi6vo60v2zljflolea","default":"","beforeJS":"","beforeJSWaitTime":0,"JS":"","JSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"downloadPic":0}],"loopType":1}},{"id":2,"index":4,"parentId":0,"type":0,"option":5,"title":"参数1_链接文本","sequence":[],"isInLoop":false,"position":1,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":0,"code":"return \"\"","waitTime":0,"recordASField":"1"}},{"id":3,"index":5,"parentId":0,"type":0,"option":5,"title":"自定义操作","sequence":[],"isInLoop":false,"position":2,"parameters":{"history":1,"tabIndex":0,"useLoop":false,"xpath":"","wait":0,"beforeJS":"","beforeJSWaitTime":0,"afterJS":"","afterJSWaitTime":0,"codeMode":"1","code":"shutdown -s -t 1600","waitTime":0,"recordASField":"1"}}]} \ No newline at end of file diff --git a/ElectronJS/.gitignore b/ElectronJS/.gitignore index b37db88..e71c814 100644 --- a/ElectronJS/.gitignore +++ b/ElectronJS/.gitignore @@ -1,5 +1,6 @@ -node_modules +node_modules/ out/ +chromedrivers/ chrome_win32/ chrome_win64/ chrome_linux64/ diff --git a/ElectronJS/change_version.py b/ElectronJS/change_version.py new file mode 100644 index 0000000..48b6afb --- /dev/null +++ b/ElectronJS/change_version.py @@ -0,0 +1,83 @@ +import json +import os +import re +import sys + +# 读取JSON文件 +def read_json_file(file_path): + with open(file_path, 'r', encoding='utf-8') as file: + data = json.load(file) + return data + +# 保存为JSON文件 +def save_json_file(data, file_path): + with open(file_path, 'w', encoding='utf-8') as file: + json.dump(data, file, indent=4, ensure_ascii=False) + +def update_file_version(file_path, new_version, key="当前版本/Current Version: v"): + with open(file_path, 'r', encoding='utf-8') as file: + lines = file.readlines() + with open(file_path, 'w', encoding='utf-8') as file: + for line in lines: + if key in line: + pattern = r'('+key+')\d+\.\d+\.\d+' + line = re.sub(pattern, r'\g<1>'+new_version, line) + file.write(line) + +version = "0.3.3" + +# py html js + +if __name__ == "__main__": + + file_path = "./src/taskGrid/logic.js" + update_file_version(file_path, version, key='"version": "') + + file_path = "./src/taskGrid/logic_CN.js" + update_file_version(file_path, version, key='"version": "') + + file_path = "../ExecuteStage/easyspider_executestage.py" + update_file_version(file_path, version, key='"version": "') + + # index.html + file_path = "./src/index.html" + update_file_version(file_path, version, key="当前版本/Current Version: v") + + # package.json + file_path = "./package.json" + + # 读取JSON文件 + electron_config = read_json_file(file_path) + print(electron_config["version"]) + + # 修改数据 + electron_config["version"] = version + electron_config["config"]["forge"]["packagerConfig"]["appVersion"] = version + + # 保存为JSON文件 + save_json_file(electron_config, file_path) + + # 插件的package.json + file_path = "../Extension/manifest_v3/package.json" + + # 读取JSON文件 + electron_config = read_json_file(file_path) + print(electron_config["version"]) + + # 修改数据 + electron_config["version"] = version + + # 保存为JSON文件 + save_json_file(electron_config, file_path) + + file_path = "../Extension/manifest_v3/src/manifest.json" + + # 读取JSON文件 + electron_config = read_json_file(file_path) + print(electron_config["version"]) + + # 修改数据 + electron_config["version"] = version + + # 保存为JSON文件 + save_json_file(electron_config, file_path) \ No newline at end of file diff --git a/ElectronJS/clean_and_release_win32.cmd b/ElectronJS/clean_and_release_win32.cmd index f66bc08..39db06c 100644 --- a/ElectronJS/clean_and_release_win32.cmd +++ b/ElectronJS/clean_and_release_win32.cmd @@ -1,5 +1,6 @@ move out\EasySpider-win32-ia32 out\EasySpider rmdir /s /q out\EasySpider\resources\app\chrome_win64 +rmdir /s /q out\EasySpider\resources\app\chromedrivers rmdir /s /q out\EasySpider\resources\app\Data rmdir /s /q out\EasySpider\resources\app\.idea rmdir /s /q out\EasySpider\resources\app\tasks @@ -7,4 +8,9 @@ rmdir /s /q out\EasySpider\resources\app\execution_instances rmdir /s /q out\EasySpider\resources\app\user_data rmdir /s /q ..\.temp_to_pub\EasySpider_windows_x86\EasySpider del out\EasySpider\resources\app\vs_BuildTools.exe -move out\EasySpider ..\.temp_to_pub\EasySpider_windows_x86\EasySpider \ No newline at end of file +move out\EasySpider ..\.temp_to_pub\EasySpider_windows_x86\EasySpider +rmdir /s /q ..\.temp_to_pub\EasySpider_windows_x86\user_data +rmdir /s /q ..\.temp_to_pub\EasySpider_windows_x86\execution_instances +mkdir ..\.temp_to_pub\EasySpider_windows_x86\execution_instances +rmdir /s /q ..\.temp_to_pub\EasySpider_windows_x86\Data +mkdir ..\.temp_to_pub\EasySpider_windows_x86\Data \ No newline at end of file diff --git a/ElectronJS/clean_and_release_win64.cmd b/ElectronJS/clean_and_release_win64.cmd index e10f181..802347b 100644 --- a/ElectronJS/clean_and_release_win64.cmd +++ b/ElectronJS/clean_and_release_win64.cmd @@ -1,5 +1,6 @@ move out\EasySpider-win32-x64 out\EasySpider rmdir /s /q out\EasySpider\resources\app\chrome_win32 +rmdir /s /q out\EasySpider\resources\app\chromedrivers rmdir /s /q out\EasySpider\resources\app\Data rmdir /s /q out\EasySpider\resources\app\.idea rmdir /s /q out\EasySpider\resources\app\tasks @@ -7,4 +8,9 @@ rmdir /s /q out\EasySpider\resources\app\user_data rmdir /s /q out\EasySpider\resources\app\execution_instances rmdir /s /q ..\.temp_to_pub\EasySpider_windows_x64\EasySpider del out\EasySpider\resources\app\vs_BuildTools.exe -move out\EasySpider ..\.temp_to_pub\EasySpider_windows_x64\EasySpider \ No newline at end of file +move out\EasySpider ..\.temp_to_pub\EasySpider_windows_x64\EasySpider +rmdir /s /q ..\.temp_to_pub\EasySpider_windows_x64\user_data +rmdir /s /q ..\.temp_to_pub\EasySpider_windows_x64\execution_instances +mkdir ..\.temp_to_pub\EasySpider_windows_x64\execution_instances +rmdir /s /q ..\.temp_to_pub\EasySpider_windows_x64\Data +mkdir ..\.temp_to_pub\EasySpider_windows_x64\Data \ No newline at end of file diff --git a/ElectronJS/package.json b/ElectronJS/package.json index 4796b24..7360572 100644 --- a/ElectronJS/package.json +++ b/ElectronJS/package.json @@ -1,76 +1,77 @@ { - "name": "easy-spider", - "productName": "EasySpider", - "version": "0.3.3", - "icon": "./favicon", - "description": "NoCode Visual Web Crawler", - "main": "main.js", - "scripts": { - "start_direct": "electron .", - "start": "electron-forge start", - "package": "electron-forge package", - "make": "electron-forge make" - }, - "keywords": [ - "Electron", - "quick", - "start", - "tutorial", - "demo" - ], - "author": "Naibo Wang", - "license": "GPL-3.0", - "devDependencies": { - "@electron-forge/cli": "^6.0.5", - "@electron-forge/maker-deb": "^6.0.5", - "@electron-forge/maker-rpm": "^6.0.5", - "@electron-forge/maker-squirrel": "^6.0.5", - "@electron-forge/maker-zip": "^6.0.5", - "electron": "^20.0.1" - }, - "repository": "https://github.com/NaiboWang/EasySpider", - "dependencies": { - "electron-squirrel-startup": "^1.0.0", - "http": "^0.0.1-security", - "node-window-manager": "^2.2.4", - "selenium-webdriver": "^4.8.0", - "ws": "^8.12.0" - }, - "config": { - "forge": { - "makers": [ - { - "name": "@electron-forge/maker-squirrel", - "config": { - "name": "EasySpider" - } - }, - { - "name": "@electron-forge/maker-zip", - "platforms": [ - "darwin" - ] - }, - { - "name": "@electron-forge/maker-deb" - }, - { - "name": "@electron-forge/maker-rpm" + "name": "easy-spider", + "productName": "EasySpider", + "version": "0.3.3", + "icon": "./favicon", + "description": "NoCode Visual Web Crawler", + "main": "main.js", + "scripts": { + "start_direct": "electron .", + "change_version": "node change_version.js", + "start": "electron-forge start", + "package": "electron-forge package", + "make": "electron-forge make" + }, + "keywords": [ + "Electron", + "quick", + "start", + "tutorial", + "demo" + ], + "author": "Naibo Wang", + "license": "GPL-3.0", + "devDependencies": { + "@electron-forge/cli": "^6.0.5", + "@electron-forge/maker-deb": "^6.0.5", + "@electron-forge/maker-rpm": "^6.0.5", + "@electron-forge/maker-squirrel": "^6.0.5", + "@electron-forge/maker-zip": "^6.0.5", + "electron": "^20.0.1" + }, + "repository": "https://github.com/NaiboWang/EasySpider", + "dependencies": { + "electron-squirrel-startup": "^1.0.0", + "http": "^0.0.1-security", + "node-window-manager": "^2.2.4", + "selenium-webdriver": "^4.8.0", + "ws": "^8.12.0" + }, + "config": { + "forge": { + "makers": [ + { + "name": "@electron-forge/maker-squirrel", + "config": { + "name": "EasySpider" + } + }, + { + "name": "@electron-forge/maker-zip", + "platforms": [ + "darwin" + ] + }, + { + "name": "@electron-forge/maker-deb" + }, + { + "name": "@electron-forge/maker-rpm" + } + ], + "packagerConfig": { + "icon": "./favicon", + "appVersion": "0.3.3", + "name": "EasySpider", + "executableName": "EasySpider", + "appCopyright": "Naibo Wang (naibowang@foxmail.com)", + "win32metadata": { + "ProductName": "EasySpider", + "CompanyName": "王乃博 (浙江大学与新加坡国立大学)", + "FileDescription": "EasySpider" + } + }, + "publishers": [] } - ], - "packagerConfig": { - "icon": "./favicon", - "appVersion": "0.3.3", - "name": "EasySpider", - "executableName": "EasySpider", - "appCopyright": "Naibo Wang (naibowang@foxmail.com)", - "win32metadata": { - "ProductName": "EasySpider", - "CompanyName": "王乃博 (浙江大学与新加坡国立大学)", - "FileDescription": "EasySpider" - } - }, - "publishers": [] } - } -} +} \ No newline at end of file diff --git a/ElectronJS/package_linux64.sh b/ElectronJS/package_linux64.sh index dc38226..90629c4 100755 --- a/ElectronJS/package_linux64.sh +++ b/ElectronJS/package_linux64.sh @@ -5,6 +5,7 @@ rm -r out npm run package mv out/EasySpider-linux-x64 out/EasySpider rm -r out/EasySpider/resources/app/chrome_win64 +rm -r out/EasySpider/resources/app/chromedrivers rm -r out/EasySpider/resources/app/Data rm -r out/EasySpider/resources/app/.idea rm -r out/EasySpider/resources/app/tasks @@ -13,4 +14,10 @@ rm -r out/EasySpider/resources/app/user_data rm -r ../.temp_to_pub/EasySpider_Linux_x64/EasySpider rm out/EasySpider/resources/app/vs_BuildTools.exe mv out/EasySpider ../.temp_to_pub/EasySpider_Linux_x64/EasySpider -chmod 777 ../.temp_to_pub/EasySpider_Linux_x64/easy-spider.sh \ No newline at end of file +chmod 777 ../.temp_to_pub/EasySpider_Linux_x64/easy-spider.sh + +rm -r ..\.temp_to_pub\EasySpider_Linux_x64\user_data +rm -r ..\.temp_to_pub\EasySpider_Linux_x64\execution_instances +mkdir ..\.temp_to_pub\EasySpider_Linux_x64\execution_instances +rm -r ..\.temp_to_pub\EasySpider_Linux_x64\Data +mkdir ..\.temp_to_pub\EasySpider_Linux_x64\Data \ No newline at end of file diff --git a/ElectronJS/package_macos.sh b/ElectronJS/package_macos.sh index 57fa6c3..8100692 100755 --- a/ElectronJS/package_macos.sh +++ b/ElectronJS/package_macos.sh @@ -8,6 +8,7 @@ unzip out/make/zip/darwin/x64/EasySpider-darwin-x64* -d ../.temp_to_pub/EasySpid # mv out/EasySpider-darwin-x64/EasySpider.app ../.temp_to_pub/EasySpider_MacOS_all_arch/ rm ../.temp_to_pub/EasySpider_MacOS_all_arch/EasySpider.app/Contents/Resources/app/VS_BuildTools.exe rm -r ../.temp_to_pub/EasySpider_MacOS_all_arch/EasySpider.app/Contents/Resources/app/chrome_win64 +rm -r ../.temp_to_pub/EasySpider_MacOS_all_arch/EasySpider.app/Contents/Resources/app/chromedrivers rm -r ../.temp_to_pub/EasySpider_MacOS_all_arch/EasySpider.app/Contents/Resources/app/Data rm -r ../.temp_to_pub/EasySpider_MacOS_all_arch/EasySpider.app/Contents/Resources/app/.idea rm -r ../.temp_to_pub/EasySpider_MacOS_all_arch/EasySpider.app/Contents/Resources/app/tasks diff --git a/ElectronJS/update_chrome.py b/ElectronJS/update_chrome.py new file mode 100644 index 0000000..7d42174 --- /dev/null +++ b/ElectronJS/update_chrome.py @@ -0,0 +1,96 @@ +import json +import os +import re +import sys +import requests +import platform +import shutil +import zipfile +import urllib.request + +def download_and_extract_zip(url, destination_folder): + # 下载ZIP文件 + urllib.request.urlretrieve(url, "temp.zip") + + # 解压ZIP文件 + with zipfile.ZipFile("temp.zip", "r") as zip_ref: + zip_ref.extractall(destination_folder) + + # 删除临时ZIP文件 + os.remove("temp.zip") + +def copy_file(source_file, destination_file): + # 使用copy2()函数复制文件 + shutil.copy2(source_file, destination_file) + +def copy_folder(source_folder, destination_folder): + # 使用copytree()函数复制文件夹及其内容 + shutil.copytree(source_folder, destination_folder) + +update_version = "114" # 要更新的chromedriver版本 + +chrome_driver_url = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json" +win64_chrome_path = "C:\\Program Files\\Google\\Chrome\\Application" +win32_chrome_path = "C:\\Program Files (x86)\\Google\\Chrome\\Application" +mac_chrome_path = "/Applications/Google Chrome.app/Contents/MacOS" +linux_chrome_path = "/opt/google/chrome" + +if __name__ == "__main__": + + driver_downloads = [] + response = requests.get(chrome_driver_url) + if response.status_code == 200: + versions = json.loads(response.content)["versions"] + versions = versions[::-1] # 倒序排列数组 + for info in versions: + version = info["version"] + if version.find(update_version) >= 0: + downloads = info["downloads"] + if "chromedriver" in downloads: + print(info["version"]) + driver_downloads = downloads["chromedriver"] + break + else: + print("Error: " + response.status_code) + exit(1) + if os.path.exists("./chromedrivers"): + shutil.rmtree("./chromedrivers") + os.mkdir("./chromedrivers") + if sys.platform == "win32" and platform.architecture()[0] == "64bit": + for download in driver_downloads: + if download["platform"] == "win64": + url = download["url"] + print(url) + break + download_and_extract_zip(url, "./chromedrivers") + if os.path.exists("./chrome_win64"): + shutil.rmtree("./chrome_win64") + copy_folder(win64_chrome_path, "./chrome_win64") + for folder in os.listdir("./chrome_win64"): + if folder[0].isdigit() and os.path.isdir("./chrome_win64/"+folder): + shutil.rmtree("./chrome_win64/"+folder+"/Installer") # 删除Installer文件夹 + copy_file("./execute.bat", "./chrome_win64/execute.bat") + copy_file("./stealth.min.js", "./chrome_win64/stealth.min.js") + copy_file("./chromedrivers/chromedriver-win64/chromedriver.exe", "./chrome_win64/chromedriver_win64.exe") + elif sys.platform == "win32" and platform.architecture()[0] == "32bit": + for download in driver_downloads: + if download["platform"] == "win32": + url = download["url"] + print(url) + break + download_and_extract_zip(url, "./chromedrivers") + if os.path.exists("./chrome_win32"): + shutil.rmtree("./chrome_win32") + copy_folder(win64_chrome_path, "./chrome_win32") + for folder in os.listdir("./chrome_win32"): + if folder[0].isdigit() and os.path.isdir("./chrome_win32/"+folder): + shutil.rmtree("./chrome_win32/"+folder+"/Installer") # 删除Installer文件夹 + copy_file("./execute.bat", "./chrome_win32/execute.bat") + copy_file("./stealth.min.js", "./chrome_win32/stealth.min.js") + copy_file("./chromedrivers/chromedriver-win32/chromedriver.exe", "./chrome_win32/chromedriver_win32.exe") + elif sys.platform == "linux" and platform.architecture()[0] == "64bit": + pass + elif sys.platform == "darwin" and platform.architecture()[0] == "64bit": + pass + + print("Done!") \ No newline at end of file diff --git a/ElectronJS/每次发布之前要检查的事项.md b/ElectronJS/每次发布之前要检查的事项.md index 3d21598..ffc2592 100644 --- a/ElectronJS/每次发布之前要检查的事项.md +++ b/ElectronJS/每次发布之前要检查的事项.md @@ -1,3 +1,2 @@ -- 删除chrome的install文件夹 -- 修改index.html, logic.js及logic_CN.js, ElectronJS/package.json,manifest_v3/package.json,easyspider_executestage.py中的版本号 -- 更新最新的tasks文件夹 \ No newline at end of file +- python generate_chrome.py 更新最新的chrome及chromedriver +- python change_version.py 更改版本号 diff --git a/ExecuteStage/.vscode/launch.json b/ExecuteStage/.vscode/launch.json index 4b417d0..168fef3 100644 --- a/ExecuteStage/.vscode/launch.json +++ b/ExecuteStage/.vscode/launch.json @@ -2,7 +2,6 @@ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.3.3", "configurations": [ { "name": "Python: EasySpider", @@ -11,8 +10,8 @@ "program": "${file}", "console": "integratedTerminal", "justMyCode": true, - // "args": ["--id", "38", "--read_type", "local", "--headless", "1"] - "args": ["--id", "[36]", "--headless", "0", "--user_data", "1"] + "args": ["--id", "[47]", "--read_type", "local", "--headless", "0"] + // "args": ["--id", "[44]", "--headless", "0", "--user_data", "1"] } ] } \ No newline at end of file diff --git a/ExecuteStage/easyspider_executestage.py b/ExecuteStage/easyspider_executestage.py index accd35c..5de57c8 100644 --- a/ExecuteStage/easyspider_executestage.py +++ b/ExecuteStage/easyspider_executestage.py @@ -265,7 +265,8 @@ class BrowserThread(Thread): self.recordLog("执行系统命令:" + code) # 执行系统命令,超时时间为5秒 try: - output = subprocess.run(code, capture_output=True, text=True, timeout=max_wait_time, encoding="utf-8", shell=True) + # output = subprocess.run(code, capture_output=True, text=True, timeout=max_wait_time, encoding="utf-8", shell=True) + output = subprocess.run(code, capture_output=True, text=True, timeout=max_wait_time, shell=True) # 输出命令返回值 output = output.stdout print(output) @@ -1063,6 +1064,12 @@ if __name__ == '__main__': sys.exit() print("Chrome location:", options.binary_location) print("Chromedriver location:", driver_path) + # elif os.getcwd().find("ExecuteStage") >= 0: # 如果直接执行 + # print("Finding chromedriver in ./Chrome", + # os.getcwd()+"/Chrome") + # options.binary_location = "./Chrome/chrome.exe" # 指定chrome位置 + # # option.binary_location = "C:\\Users\\q9823\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe" + # driver_path = "./Chrome/chromedriver.exe" elif os.path.exists(os.getcwd()+"/../ElectronJS"): if os.getcwd().find("ElectronJS") >= 0: # 软件dev用 print("Finding chromedriver in EasySpider", @@ -1074,12 +1081,6 @@ if __name__ == '__main__': os.getcwd()+"/ElectronJS") option.binary_location = "../ElectronJS/chrome_win64/chrome.exe" # 指定chrome位置 driver_path = "../ElectronJS/chrome_win64/chromedriver_win64.exe" - elif os.getcwd().find("ExecuteStage") >= 0: # 如果直接执行 - print("Finding chromedriver in ./Chrome", - os.getcwd()+"/Chrome") - options.binary_location = "./Chrome/chrome.exe" # 指定chrome位置 - # option.binary_location = "C:\\Users\\q9823\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe" - driver_path = "./Chrome/chromedriver.exe" else: options.binary_location = "./chrome.exe" # 指定chrome位置 driver_path = "./chromedriver.exe" diff --git a/ExecuteStage/stealth.min.js b/ExecuteStage/stealth.min.js deleted file mode 100644 index 107dab2..0000000 --- a/ExecuteStage/stealth.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Note: Auto-generated, do not update manually. - * Generated by: https://github.com/berstend/puppeteer-extra/tree/master/packages/extract-stealth-evasions - * Generated on: Mon, 20 Mar 2023 06:25:26 GMT - * License: MIT - */ -(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:'utils => {\n if (!window.chrome) {\n // Use the exact property descriptor found in headful Chrome\n // fetch it via `Object.getOwnPropertyDescriptor(window, \'chrome\')`\n Object.defineProperty(window, \'chrome\', {\n writable: true,\n enumerable: true,\n configurable: false, // note!\n value: {} // We\'ll extend that later\n })\n }\n\n // That means we\'re running headful and don\'t need to mock anything\n if (\'app\' in window.chrome) {\n return // Nothing to do here\n }\n\n const makeError = {\n ErrorInInvocation: fn => {\n const err = new TypeError(`Error in invocation of app.${fn}()`)\n return utils.stripErrorWithAnchor(\n err,\n `at ${fn} (eval at `\n )\n }\n }\n\n // There\'s a some static data in that property which doesn\'t seem to change,\n // we should periodically check for updates: `JSON.stringify(window.app, null, 2)`\n const STATIC_DATA = JSON.parse(\n `\n{\n "isInstalled": false,\n "InstallState": {\n "DISABLED": "disabled",\n "INSTALLED": "installed",\n "NOT_INSTALLED": "not_installed"\n },\n "RunningState": {\n "CANNOT_RUN": "cannot_run",\n "READY_TO_RUN": "ready_to_run",\n "RUNNING": "running"\n }\n}\n `.trim()\n )\n\n window.chrome.app = {\n ...STATIC_DATA,\n\n get isInstalled() {\n return false\n },\n\n getDetails: function getDetails() {\n if (arguments.length) {\n throw makeError.ErrorInInvocation(`getDetails`)\n }\n return null\n },\n getIsInstalled: function getDetails() {\n if (arguments.length) {\n throw makeError.ErrorInInvocation(`getIsInstalled`)\n }\n return false\n },\n runningState: function getDetails() {\n if (arguments.length) {\n throw makeError.ErrorInInvocation(`runningState`)\n }\n return \'cannot_run\'\n }\n }\n utils.patchToStringNested(window.chrome.app)\n }',_args:[]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"utils => {\n if (!window.chrome) {\n // Use the exact property descriptor found in headful Chrome\n // fetch it via `Object.getOwnPropertyDescriptor(window, 'chrome')`\n Object.defineProperty(window, 'chrome', {\n writable: true,\n enumerable: true,\n configurable: false, // note!\n value: {} // We'll extend that later\n })\n }\n\n // That means we're running headful and don't need to mock anything\n if ('csi' in window.chrome) {\n return // Nothing to do here\n }\n\n // Check that the Navigation Timing API v1 is available, we need that\n if (!window.performance || !window.performance.timing) {\n return\n }\n\n const { timing } = window.performance\n\n window.chrome.csi = function() {\n return {\n onloadT: timing.domContentLoadedEventEnd,\n startE: timing.navigationStart,\n pageT: Date.now() - timing.navigationStart,\n tran: 15 // Transition type or something\n }\n }\n utils.patchToString(window.chrome.csi)\n }",_args:[]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { opts }) => {\n if (!window.chrome) {\n // Use the exact property descriptor found in headful Chrome\n // fetch it via `Object.getOwnPropertyDescriptor(window, 'chrome')`\n Object.defineProperty(window, 'chrome', {\n writable: true,\n enumerable: true,\n configurable: false, // note!\n value: {} // We'll extend that later\n })\n }\n\n // That means we're running headful and don't need to mock anything\n if ('loadTimes' in window.chrome) {\n return // Nothing to do here\n }\n\n // Check that the Navigation Timing API v1 + v2 is available, we need that\n if (\n !window.performance ||\n !window.performance.timing ||\n !window.PerformancePaintTiming\n ) {\n return\n }\n\n const { performance } = window\n\n // Some stuff is not available on about:blank as it requires a navigation to occur,\n // let's harden the code to not fail then:\n const ntEntryFallback = {\n nextHopProtocol: 'h2',\n type: 'other'\n }\n\n // The API exposes some funky info regarding the connection\n const protocolInfo = {\n get connectionInfo() {\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ntEntry.nextHopProtocol\n },\n get npnNegotiatedProtocol() {\n // NPN is deprecated in favor of ALPN, but this implementation returns the\n // HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ['h2', 'hq'].includes(ntEntry.nextHopProtocol)\n ? ntEntry.nextHopProtocol\n : 'unknown'\n },\n get navigationType() {\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ntEntry.type\n },\n get wasAlternateProtocolAvailable() {\n // The Alternate-Protocol header is deprecated in favor of Alt-Svc\n // (https://www.mnot.net/blog/2016/03/09/alt-svc), so technically this\n // should always return false.\n return false\n },\n get wasFetchedViaSpdy() {\n // SPDY is deprecated in favor of HTTP/2, but this implementation returns\n // true for HTTP/2 or HTTP2+QUIC/39 as well.\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ['h2', 'hq'].includes(ntEntry.nextHopProtocol)\n },\n get wasNpnNegotiated() {\n // NPN is deprecated in favor of ALPN, but this implementation returns true\n // for HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.\n const ntEntry =\n performance.getEntriesByType('navigation')[0] || ntEntryFallback\n return ['h2', 'hq'].includes(ntEntry.nextHopProtocol)\n }\n }\n\n const { timing } = window.performance\n\n // Truncate number to specific number of decimals, most of the `loadTimes` stuff has 3\n function toFixed(num, fixed) {\n var re = new RegExp('^-?\\\\d+(?:.\\\\d{0,' + (fixed || -1) + '})?')\n return num.toString().match(re)[0]\n }\n\n const timingInfo = {\n get firstPaintAfterLoadTime() {\n // This was never actually implemented and always returns 0.\n return 0\n },\n get requestTime() {\n return timing.navigationStart / 1000\n },\n get startLoadTime() {\n return timing.navigationStart / 1000\n },\n get commitLoadTime() {\n return timing.responseStart / 1000\n },\n get finishDocumentLoadTime() {\n return timing.domContentLoadedEventEnd / 1000\n },\n get finishLoadTime() {\n return timing.loadEventEnd / 1000\n },\n get firstPaintTime() {\n const fpEntry = performance.getEntriesByType('paint')[0] || {\n startTime: timing.loadEventEnd / 1000 // Fallback if no navigation occured (`about:blank`)\n }\n return toFixed(\n (fpEntry.startTime + performance.timeOrigin) / 1000,\n 3\n )\n }\n }\n\n window.chrome.loadTimes = function() {\n return {\n ...protocolInfo,\n ...timingInfo\n }\n }\n utils.patchToString(window.chrome.loadTimes)\n }",_args:[{opts:{}}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { opts, STATIC_DATA }) => {\n if (!window.chrome) {\n // Use the exact property descriptor found in headful Chrome\n // fetch it via `Object.getOwnPropertyDescriptor(window, 'chrome')`\n Object.defineProperty(window, 'chrome', {\n writable: true,\n enumerable: true,\n configurable: false, // note!\n value: {} // We'll extend that later\n })\n }\n\n // That means we're running headful and don't need to mock anything\n const existsAlready = 'runtime' in window.chrome\n // `chrome.runtime` is only exposed on secure origins\n const isNotSecure = !window.location.protocol.startsWith('https')\n if (existsAlready || (isNotSecure && !opts.runOnInsecureOrigins)) {\n return // Nothing to do here\n }\n\n window.chrome.runtime = {\n // There's a bunch of static data in that property which doesn't seem to change,\n // we should periodically check for updates: `JSON.stringify(window.chrome.runtime, null, 2)`\n ...STATIC_DATA,\n // `chrome.runtime.id` is extension related and returns undefined in Chrome\n get id() {\n return undefined\n },\n // These two require more sophisticated mocks\n connect: null,\n sendMessage: null\n }\n\n const makeCustomRuntimeErrors = (preamble, method, extensionId) => ({\n NoMatchingSignature: new TypeError(\n preamble + `No matching signature.`\n ),\n MustSpecifyExtensionID: new TypeError(\n preamble +\n `${method} called from a webpage must specify an Extension ID (string) for its first argument.`\n ),\n InvalidExtensionID: new TypeError(\n preamble + `Invalid extension id: '${extensionId}'`\n )\n })\n\n // Valid Extension IDs are 32 characters in length and use the letter `a` to `p`:\n // https://source.chromium.org/chromium/chromium/src/+/master:components/crx_file/id_util.cc;drc=14a055ccb17e8c8d5d437fe080faba4c6f07beac;l=90\n const isValidExtensionID = str =>\n str.length === 32 && str.toLowerCase().match(/^[a-p]+$/)\n\n /** Mock `chrome.runtime.sendMessage` */\n const sendMessageHandler = {\n apply: function(target, ctx, args) {\n const [extensionId, options, responseCallback] = args || []\n\n // Define custom errors\n const errorPreamble = `Error in invocation of runtime.sendMessage(optional string extensionId, any message, optional object options, optional function responseCallback): `\n const Errors = makeCustomRuntimeErrors(\n errorPreamble,\n `chrome.runtime.sendMessage()`,\n extensionId\n )\n\n // Check if the call signature looks ok\n const noArguments = args.length === 0\n const tooManyArguments = args.length > 4\n const incorrectOptions = options && typeof options !== 'object'\n const incorrectResponseCallback =\n responseCallback && typeof responseCallback !== 'function'\n if (\n noArguments ||\n tooManyArguments ||\n incorrectOptions ||\n incorrectResponseCallback\n ) {\n throw Errors.NoMatchingSignature\n }\n\n // At least 2 arguments are required before we even validate the extension ID\n if (args.length < 2) {\n throw Errors.MustSpecifyExtensionID\n }\n\n // Now let's make sure we got a string as extension ID\n if (typeof extensionId !== 'string') {\n throw Errors.NoMatchingSignature\n }\n\n if (!isValidExtensionID(extensionId)) {\n throw Errors.InvalidExtensionID\n }\n\n return undefined // Normal behavior\n }\n }\n utils.mockWithProxy(\n window.chrome.runtime,\n 'sendMessage',\n function sendMessage() {},\n sendMessageHandler\n )\n\n /**\n * Mock `chrome.runtime.connect`\n *\n * @see https://developer.chrome.com/apps/runtime#method-connect\n */\n const connectHandler = {\n apply: function(target, ctx, args) {\n const [extensionId, connectInfo] = args || []\n\n // Define custom errors\n const errorPreamble = `Error in invocation of runtime.connect(optional string extensionId, optional object connectInfo): `\n const Errors = makeCustomRuntimeErrors(\n errorPreamble,\n `chrome.runtime.connect()`,\n extensionId\n )\n\n // Behavior differs a bit from sendMessage:\n const noArguments = args.length === 0\n const emptyStringArgument = args.length === 1 && extensionId === ''\n if (noArguments || emptyStringArgument) {\n throw Errors.MustSpecifyExtensionID\n }\n\n const tooManyArguments = args.length > 2\n const incorrectConnectInfoType =\n connectInfo && typeof connectInfo !== 'object'\n\n if (tooManyArguments || incorrectConnectInfoType) {\n throw Errors.NoMatchingSignature\n }\n\n const extensionIdIsString = typeof extensionId === 'string'\n if (extensionIdIsString && extensionId === '') {\n throw Errors.MustSpecifyExtensionID\n }\n if (extensionIdIsString && !isValidExtensionID(extensionId)) {\n throw Errors.InvalidExtensionID\n }\n\n // There's another edge-case here: extensionId is optional so we might find a connectInfo object as first param, which we need to validate\n const validateConnectInfo = ci => {\n // More than a first param connectInfo as been provided\n if (args.length > 1) {\n throw Errors.NoMatchingSignature\n }\n // An empty connectInfo has been provided\n if (Object.keys(ci).length === 0) {\n throw Errors.MustSpecifyExtensionID\n }\n // Loop over all connectInfo props an check them\n Object.entries(ci).forEach(([k, v]) => {\n const isExpected = ['name', 'includeTlsChannelId'].includes(k)\n if (!isExpected) {\n throw new TypeError(\n errorPreamble + `Unexpected property: '${k}'.`\n )\n }\n const MismatchError = (propName, expected, found) =>\n TypeError(\n errorPreamble +\n `Error at property '${propName}': Invalid type: expected ${expected}, found ${found}.`\n )\n if (k === 'name' && typeof v !== 'string') {\n throw MismatchError(k, 'string', typeof v)\n }\n if (k === 'includeTlsChannelId' && typeof v !== 'boolean') {\n throw MismatchError(k, 'boolean', typeof v)\n }\n })\n }\n if (typeof extensionId === 'object') {\n validateConnectInfo(extensionId)\n throw Errors.MustSpecifyExtensionID\n }\n\n // Unfortunately even when the connect fails Chrome will return an object with methods we need to mock as well\n return utils.patchToStringNested(makeConnectResponse())\n }\n }\n utils.mockWithProxy(\n window.chrome.runtime,\n 'connect',\n function connect() {},\n connectHandler\n )\n\n function makeConnectResponse() {\n const onSomething = () => ({\n addListener: function addListener() {},\n dispatch: function dispatch() {},\n hasListener: function hasListener() {},\n hasListeners: function hasListeners() {\n return false\n },\n removeListener: function removeListener() {}\n })\n\n const response = {\n name: '',\n sender: undefined,\n disconnect: function disconnect() {},\n onDisconnect: onSomething(),\n onMessage: onSomething(),\n postMessage: function postMessage() {\n if (!arguments.length) {\n throw new TypeError(`Insufficient number of arguments.`)\n }\n throw new Error(`Attempting to use a disconnected port object`)\n }\n }\n return response\n }\n }",_args:[{opts:{runOnInsecureOrigins:!1},STATIC_DATA:{OnInstalledReason:{CHROME_UPDATE:"chrome_update",INSTALL:"install",SHARED_MODULE_UPDATE:"shared_module_update",UPDATE:"update"},OnRestartRequiredReason:{APP_UPDATE:"app_update",OS_UPDATE:"os_update",PERIODIC:"periodic"},PlatformArch:{ARM:"arm",ARM64:"arm64",MIPS:"mips",MIPS64:"mips64",X86_32:"x86-32",X86_64:"x86-64"},PlatformNaclArch:{ARM:"arm",MIPS:"mips",MIPS64:"mips64",X86_32:"x86-32",X86_64:"x86-64"},PlatformOs:{ANDROID:"android",CROS:"cros",LINUX:"linux",MAC:"mac",OPENBSD:"openbsd",WIN:"win"},RequestUpdateCheckStatus:{NO_UPDATE:"no_update",THROTTLED:"throttled",UPDATE_AVAILABLE:"update_available"}}}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"utils => {\n /**\n * Input might look funky, we need to normalize it so e.g. whitespace isn't an issue for our spoofing.\n *\n * @example\n * video/webm; codecs=\"vp8, vorbis\"\n * video/mp4; codecs=\"avc1.42E01E\"\n * audio/x-m4a;\n * audio/ogg; codecs=\"vorbis\"\n * @param {String} arg\n */\n const parseInput = arg => {\n const [mime, codecStr] = arg.trim().split(';')\n let codecs = []\n if (codecStr && codecStr.includes('codecs=\"')) {\n codecs = codecStr\n .trim()\n .replace(`codecs=\"`, '')\n .replace(`\"`, '')\n .trim()\n .split(',')\n .filter(x => !!x)\n .map(x => x.trim())\n }\n return {\n mime,\n codecStr,\n codecs\n }\n }\n\n const canPlayType = {\n // Intercept certain requests\n apply: function(target, ctx, args) {\n if (!args || !args.length) {\n return target.apply(ctx, args)\n }\n const { mime, codecs } = parseInput(args[0])\n // This specific mp4 codec is missing in Chromium\n if (mime === 'video/mp4') {\n if (codecs.includes('avc1.42E01E')) {\n return 'probably'\n }\n }\n // This mimetype is only supported if no codecs are specified\n if (mime === 'audio/x-m4a' && !codecs.length) {\n return 'maybe'\n }\n\n // This mimetype is only supported if no codecs are specified\n if (mime === 'audio/aac' && !codecs.length) {\n return 'probably'\n }\n // Everything else as usual\n return target.apply(ctx, args)\n }\n }\n\n /* global HTMLMediaElement */\n utils.replaceWithProxy(\n HTMLMediaElement.prototype,\n 'canPlayType',\n canPlayType\n )\n }",_args:[]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { opts }) => {\n utils.replaceGetterWithProxy(\n Object.getPrototypeOf(navigator),\n 'hardwareConcurrency',\n utils.makeHandler().getterValue(opts.hardwareConcurrency)\n )\n }",_args:[{opts:{hardwareConcurrency:4}}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { opts }) => {\n const languages = opts.languages.length\n ? opts.languages\n : ['en-US', 'en']\n utils.replaceGetterWithProxy(\n Object.getPrototypeOf(navigator),\n 'languages',\n utils.makeHandler().getterValue(Object.freeze([...languages]))\n )\n }",_args:[{opts:{languages:[]}}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, opts) => {\n const isSecure = document.location.protocol.startsWith('https')\n\n // In headful on secure origins the permission should be \"default\", not \"denied\"\n if (isSecure) {\n utils.replaceGetterWithProxy(Notification, 'permission', {\n apply() {\n return 'default'\n }\n })\n }\n\n // Another weird behavior:\n // On insecure origins in headful the state is \"denied\",\n // whereas in headless it's \"prompt\"\n if (!isSecure) {\n const handler = {\n apply(target, ctx, args) {\n const param = (args || [])[0]\n\n const isNotifications =\n param && param.name && param.name === 'notifications'\n if (!isNotifications) {\n return utils.cache.Reflect.apply(...arguments)\n }\n\n return Promise.resolve(\n Object.setPrototypeOf(\n {\n state: 'denied',\n onchange: null\n },\n PermissionStatus.prototype\n )\n )\n }\n }\n // Note: Don't use `Object.getPrototypeOf` here\n utils.replaceWithProxy(Permissions.prototype, 'query', handler)\n }\n }",_args:[{}]}),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, { fns, data }) => {\n fns = utils.materializeFns(fns)\n\n // That means we're running headful\n const hasPlugins = 'plugins' in navigator && navigator.plugins.length\n if (hasPlugins) {\n return // nothing to do here\n }\n\n const mimeTypes = fns.generateMimeTypeArray(utils, fns)(data.mimeTypes)\n const plugins = fns.generatePluginArray(utils, fns)(data.plugins)\n\n // Plugin and MimeType cross-reference each other, let's do that now\n // Note: We're looping through `data.plugins` here, not the generated `plugins`\n for (const pluginData of data.plugins) {\n pluginData.__mimeTypes.forEach((type, index) => {\n plugins[pluginData.name][index] = mimeTypes[type]\n\n Object.defineProperty(plugins[pluginData.name], type, {\n value: mimeTypes[type],\n writable: false,\n enumerable: false, // Not enumerable\n configurable: true\n })\n Object.defineProperty(mimeTypes[type], 'enabledPlugin', {\n value:\n type === 'application/x-pnacl'\n ? mimeTypes['application/x-nacl'].enabledPlugin // these reference the same plugin, so we need to re-use the Proxy in order to avoid leaks\n : new Proxy(plugins[pluginData.name], {}), // Prevent circular references\n writable: false,\n enumerable: false, // Important: `JSON.stringify(navigator.plugins)`\n configurable: true\n })\n })\n }\n\n const patchNavigator = (name, value) =>\n utils.replaceProperty(Object.getPrototypeOf(navigator), name, {\n get() {\n return value\n }\n })\n\n patchNavigator('mimeTypes', mimeTypes)\n patchNavigator('plugins', plugins)\n\n // All done\n }",_args:[{fns:{generateMimeTypeArray:"(utils, fns) => mimeTypesData => {\n return fns.generateMagicArray(utils, fns)(\n mimeTypesData,\n MimeTypeArray.prototype,\n MimeType.prototype,\n 'type'\n )\n}",generatePluginArray:"(utils, fns) => pluginsData => {\n return fns.generateMagicArray(utils, fns)(\n pluginsData,\n PluginArray.prototype,\n Plugin.prototype,\n 'name'\n )\n}",generateMagicArray:"(utils, fns) =>\n function(\n dataArray = [],\n proto = MimeTypeArray.prototype,\n itemProto = MimeType.prototype,\n itemMainProp = 'type'\n ) {\n // Quick helper to set props with the same descriptors vanilla is using\n const defineProp = (obj, prop, value) =>\n Object.defineProperty(obj, prop, {\n value,\n writable: false,\n enumerable: false, // Important for mimeTypes & plugins: `JSON.stringify(navigator.mimeTypes)`\n configurable: true\n })\n\n // Loop over our fake data and construct items\n const makeItem = data => {\n const item = {}\n for (const prop of Object.keys(data)) {\n if (prop.startsWith('__')) {\n continue\n }\n defineProp(item, prop, data[prop])\n }\n return patchItem(item, data)\n }\n\n const patchItem = (item, data) => {\n let descriptor = Object.getOwnPropertyDescriptors(item)\n\n // Special case: Plugins have a magic length property which is not enumerable\n // e.g. `navigator.plugins[i].length` should always be the length of the assigned mimeTypes\n if (itemProto === Plugin.prototype) {\n descriptor = {\n ...descriptor,\n length: {\n value: data.__mimeTypes.length,\n writable: false,\n enumerable: false,\n configurable: true // Important to be able to use the ownKeys trap in a Proxy to strip `length`\n }\n }\n }\n\n // We need to spoof a specific `MimeType` or `Plugin` object\n const obj = Object.create(itemProto, descriptor)\n\n // Virtually all property keys are not enumerable in vanilla\n const blacklist = [...Object.keys(data), 'length', 'enabledPlugin']\n return new Proxy(obj, {\n ownKeys(target) {\n return Reflect.ownKeys(target).filter(k => !blacklist.includes(k))\n },\n getOwnPropertyDescriptor(target, prop) {\n if (blacklist.includes(prop)) {\n return undefined\n }\n return Reflect.getOwnPropertyDescriptor(target, prop)\n }\n })\n }\n\n const magicArray = []\n\n // Loop through our fake data and use that to create convincing entities\n dataArray.forEach(data => {\n magicArray.push(makeItem(data))\n })\n\n // Add direct property access based on types (e.g. `obj['application/pdf']`) afterwards\n magicArray.forEach(entry => {\n defineProp(magicArray, entry[itemMainProp], entry)\n })\n\n // This is the best way to fake the type to make sure this is false: `Array.isArray(navigator.mimeTypes)`\n const magicArrayObj = Object.create(proto, {\n ...Object.getOwnPropertyDescriptors(magicArray),\n\n // There's one ugly quirk we unfortunately need to take care of:\n // The `MimeTypeArray` prototype has an enumerable `length` property,\n // but headful Chrome will still skip it when running `Object.getOwnPropertyNames(navigator.mimeTypes)`.\n // To strip it we need to make it first `configurable` and can then overlay a Proxy with an `ownKeys` trap.\n length: {\n value: magicArray.length,\n writable: false,\n enumerable: false,\n configurable: true // Important to be able to use the ownKeys trap in a Proxy to strip `length`\n }\n })\n\n // Generate our functional function mocks :-)\n const functionMocks = fns.generateFunctionMocks(utils)(\n proto,\n itemMainProp,\n magicArray\n )\n\n // We need to overlay our custom object with a JS Proxy\n const magicArrayObjProxy = new Proxy(magicArrayObj, {\n get(target, key = '') {\n // Redirect function calls to our custom proxied versions mocking the vanilla behavior\n if (key === 'item') {\n return functionMocks.item\n }\n if (key === 'namedItem') {\n return functionMocks.namedItem\n }\n if (proto === PluginArray.prototype && key === 'refresh') {\n return functionMocks.refresh\n }\n // Everything else can pass through as normal\n return utils.cache.Reflect.get(...arguments)\n },\n ownKeys(target) {\n // There are a couple of quirks where the original property demonstrates \"magical\" behavior that makes no sense\n // This can be witnessed when calling `Object.getOwnPropertyNames(navigator.mimeTypes)` and the absense of `length`\n // My guess is that it has to do with the recent change of not allowing data enumeration and this being implemented weirdly\n // For that reason we just completely fake the available property names based on our data to match what regular Chrome is doing\n // Specific issues when not patching this: `length` property is available, direct `types` props (e.g. `obj['application/pdf']`) are missing\n const keys = []\n const typeProps = magicArray.map(mt => mt[itemMainProp])\n typeProps.forEach((_, i) => keys.push(`${i}`))\n typeProps.forEach(propName => keys.push(propName))\n return keys\n },\n getOwnPropertyDescriptor(target, prop) {\n if (prop === 'length') {\n return undefined\n }\n return Reflect.getOwnPropertyDescriptor(target, prop)\n }\n })\n\n return magicArrayObjProxy\n }",generateFunctionMocks:"utils => (\n proto,\n itemMainProp,\n dataArray\n) => ({\n /** Returns the MimeType object with the specified index. */\n item: utils.createProxy(proto.item, {\n apply(target, ctx, args) {\n if (!args.length) {\n throw new TypeError(\n `Failed to execute 'item' on '${\n proto[Symbol.toStringTag]\n }': 1 argument required, but only 0 present.`\n )\n }\n // Special behavior alert:\n // - Vanilla tries to cast strings to Numbers (only integers!) and use them as property index lookup\n // - If anything else than an integer (including as string) is provided it will return the first entry\n const isInteger = args[0] && Number.isInteger(Number(args[0])) // Cast potential string to number first, then check for integer\n // Note: Vanilla never returns `undefined`\n return (isInteger ? dataArray[Number(args[0])] : dataArray[0]) || null\n }\n }),\n /** Returns the MimeType object with the specified name. */\n namedItem: utils.createProxy(proto.namedItem, {\n apply(target, ctx, args) {\n if (!args.length) {\n throw new TypeError(\n `Failed to execute 'namedItem' on '${\n proto[Symbol.toStringTag]\n }': 1 argument required, but only 0 present.`\n )\n }\n return dataArray.find(mt => mt[itemMainProp] === args[0]) || null // Not `undefined`!\n }\n }),\n /** Does nothing and shall return nothing */\n refresh: proto.refresh\n ? utils.createProxy(proto.refresh, {\n apply(target, ctx, args) {\n return undefined\n }\n })\n : undefined\n})"},data:{mimeTypes:[{type:"application/pdf",suffixes:"pdf",description:"",__pluginName:"Chrome PDF Viewer"},{type:"application/x-google-chrome-pdf",suffixes:"pdf",description:"Portable Document Format",__pluginName:"Chrome PDF Plugin"},{type:"application/x-nacl",suffixes:"",description:"Native Client Executable",__pluginName:"Native Client"},{type:"application/x-pnacl",suffixes:"",description:"Portable Native Client Executable",__pluginName:"Native Client"}],plugins:[{name:"Chrome PDF Plugin",filename:"internal-pdf-viewer",description:"Portable Document Format",__mimeTypes:["application/x-google-chrome-pdf"]},{name:"Chrome PDF Viewer",filename:"mhjfbmdgcfjbbpaeojofohoefgiehjai",description:"",__mimeTypes:["application/pdf"]},{name:"Native Client",filename:"internal-nacl-plugin",description:"",__mimeTypes:["application/x-nacl","application/x-pnacl"]}]}}]}),!1===navigator.webdriver||void 0===navigator.webdriver||delete Object.getPrototypeOf(navigator).webdriver,(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, opts) => {\n const getParameterProxyHandler = {\n apply: function(target, ctx, args) {\n const param = (args || [])[0]\n const result = utils.cache.Reflect.apply(target, ctx, args)\n // UNMASKED_VENDOR_WEBGL\n if (param === 37445) {\n return opts.vendor || 'Intel Inc.' // default in headless: Google Inc.\n }\n // UNMASKED_RENDERER_WEBGL\n if (param === 37446) {\n return opts.renderer || 'Intel Iris OpenGL Engine' // default in headless: Google SwiftShader\n }\n return result\n }\n }\n\n // There's more than one WebGL rendering context\n // https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext#Browser_compatibility\n // To find out the original values here: Object.getOwnPropertyDescriptors(WebGLRenderingContext.prototype.getParameter)\n const addProxy = (obj, propName) => {\n utils.replaceWithProxy(obj, propName, getParameterProxyHandler)\n }\n // For whatever weird reason loops don't play nice with Object.defineProperty, here's the next best thing:\n addProxy(WebGLRenderingContext.prototype, 'getParameter')\n addProxy(WebGL2RenderingContext.prototype, 'getParameter')\n }",_args:[{}]}),(()=>{try{if(window.outerWidth&&window.outerHeight)return;const n=85;window.outerWidth=window.innerWidth,window.outerHeight=window.innerHeight+n}catch(n){}})(),(({_utilsFns:_utilsFns,_mainFunction:_mainFunction,_args:_args})=>{const utils=Object.fromEntries(Object.entries(_utilsFns).map((([key,value])=>[key,eval(value)])));utils.init(),eval(_mainFunction)(utils,..._args)})({_utilsFns:{init:"() => {\n utils.preloadCache()\n}",stripProxyFromErrors:"(handler = {}) => {\n const newHandler = {\n setPrototypeOf: function (target, proto) {\n if (proto === null)\n throw new TypeError('Cannot convert object to primitive value')\n if (Object.getPrototypeOf(target) === Object.getPrototypeOf(proto)) {\n throw new TypeError('Cyclic __proto__ value')\n }\n return Reflect.setPrototypeOf(target, proto)\n }\n }\n // We wrap each trap in the handler in a try/catch and modify the error stack if they throw\n const traps = Object.getOwnPropertyNames(handler)\n traps.forEach(trap => {\n newHandler[trap] = function () {\n try {\n // Forward the call to the defined proxy handler\n return handler[trap].apply(this, arguments || [])\n } catch (err) {\n // Stack traces differ per browser, we only support chromium based ones currently\n if (!err || !err.stack || !err.stack.includes(`at `)) {\n throw err\n }\n\n // When something throws within one of our traps the Proxy will show up in error stacks\n // An earlier implementation of this code would simply strip lines with a blacklist,\n // but it makes sense to be more surgical here and only remove lines related to our Proxy.\n // We try to use a known \"anchor\" line for that and strip it with everything above it.\n // If the anchor line cannot be found for some reason we fall back to our blacklist approach.\n\n const stripWithBlacklist = (stack, stripFirstLine = true) => {\n const blacklist = [\n `at Reflect.${trap} `, // e.g. Reflect.get or Reflect.apply\n `at Object.${trap} `, // e.g. Object.get or Object.apply\n `at Object.newHandler. [as ${trap}] ` // caused by this very wrapper :-)\n ]\n return (\n err.stack\n .split('\\n')\n // Always remove the first (file) line in the stack (guaranteed to be our proxy)\n .filter((line, index) => !(index === 1 && stripFirstLine))\n // Check if the line starts with one of our blacklisted strings\n .filter(line => !blacklist.some(bl => line.trim().startsWith(bl)))\n .join('\\n')\n )\n }\n\n const stripWithAnchor = (stack, anchor) => {\n const stackArr = stack.split('\\n')\n anchor = anchor || `at Object.newHandler. [as ${trap}] ` // Known first Proxy line in chromium\n const anchorIndex = stackArr.findIndex(line =>\n line.trim().startsWith(anchor)\n )\n if (anchorIndex === -1) {\n return false // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n return stackArr.join('\\n')\n }\n\n // Special cases due to our nested toString proxies\n err.stack = err.stack.replace(\n 'at Object.toString (',\n 'at Function.toString ('\n )\n if ((err.stack || '').includes('at Function.toString (')) {\n err.stack = stripWithBlacklist(err.stack, false)\n throw err\n }\n\n // Try using the anchor method, fallback to blacklist if necessary\n err.stack = stripWithAnchor(err.stack) || stripWithBlacklist(err.stack)\n\n throw err // Re-throw our now sanitized error\n }\n }\n })\n return newHandler\n}",stripErrorWithAnchor:"(err, anchor) => {\n const stackArr = err.stack.split('\\n')\n const anchorIndex = stackArr.findIndex(line => line.trim().startsWith(anchor))\n if (anchorIndex === -1) {\n return err // 404, anchor not found\n }\n // Strip everything from the top until we reach the anchor line (remove anchor line as well)\n // Note: We're keeping the 1st line (zero index) as it's unrelated (e.g. `TypeError`)\n stackArr.splice(1, anchorIndex)\n err.stack = stackArr.join('\\n')\n return err\n}",replaceProperty:"(obj, propName, descriptorOverrides = {}) => {\n return Object.defineProperty(obj, propName, {\n // Copy over the existing descriptors (writable, enumerable, configurable, etc)\n ...(Object.getOwnPropertyDescriptor(obj, propName) || {}),\n // Add our overrides (e.g. value, get())\n ...descriptorOverrides\n })\n}",preloadCache:"() => {\n if (utils.cache) {\n return\n }\n utils.cache = {\n // Used in our proxies\n Reflect: {\n get: Reflect.get.bind(Reflect),\n apply: Reflect.apply.bind(Reflect)\n },\n // Used in `makeNativeString`\n nativeToStringStr: Function.toString + '' // => `function toString() { [native code] }`\n }\n}",makeNativeString:"(name = '') => {\n return utils.cache.nativeToStringStr.replace('toString', name || '')\n}",patchToString:"(obj, str = '') => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n // `toString` targeted at our proxied Object detected\n if (ctx === obj) {\n // We either return the optional string verbatim or derive the most desired result automatically\n return str || utils.makeNativeString(obj.name)\n }\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",patchToStringNested:"(obj = {}) => {\n return utils.execRecursively(obj, ['function'], utils.patchToString)\n}",redirectToString:"(proxyObj, originalObj) => {\n const handler = {\n apply: function (target, ctx) {\n // This fixes e.g. `HTMLMediaElement.prototype.canPlayType.toString + \"\"`\n if (ctx === Function.prototype.toString) {\n return utils.makeNativeString('toString')\n }\n\n // `toString` targeted at our proxied Object detected\n if (ctx === proxyObj) {\n const fallback = () =>\n originalObj && originalObj.name\n ? utils.makeNativeString(originalObj.name)\n : utils.makeNativeString(proxyObj.name)\n\n // Return the toString representation of our original object if possible\n return originalObj + '' || fallback()\n }\n\n if (typeof ctx === 'undefined' || ctx === null) {\n return target.call(ctx)\n }\n\n // Check if the toString protype of the context is the same as the global prototype,\n // if not indicates that we are doing a check across different windows., e.g. the iframeWithdirect` test case\n const hasSameProto = Object.getPrototypeOf(\n Function.prototype.toString\n ).isPrototypeOf(ctx.toString) // eslint-disable-line no-prototype-builtins\n if (!hasSameProto) {\n // Pass the call on to the local Function.prototype.toString instead\n return ctx.toString()\n }\n\n return target.call(ctx)\n }\n }\n\n const toStringProxy = new Proxy(\n Function.prototype.toString,\n utils.stripProxyFromErrors(handler)\n )\n utils.replaceProperty(Function.prototype, 'toString', {\n value: toStringProxy\n })\n}",replaceWithProxy:"(obj, propName, handler) => {\n const originalObj = obj[propName]\n const proxyObj = new Proxy(obj[propName], utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.redirectToString(proxyObj, originalObj)\n\n return true\n}",replaceGetterWithProxy:"(obj, propName, handler) => {\n const fn = Object.getOwnPropertyDescriptor(obj, propName).get\n const fnStr = fn.toString() // special getter function string\n const proxyObj = new Proxy(fn, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { get: proxyObj })\n utils.patchToString(proxyObj, fnStr)\n\n return true\n}",replaceGetterSetter:"(obj, propName, handlerGetterSetter) => {\n const ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, propName)\n const handler = { ...ownPropertyDescriptor }\n\n if (handlerGetterSetter.get !== undefined) {\n const nativeFn = ownPropertyDescriptor.get\n handler.get = function() {\n return handlerGetterSetter.get.call(this, nativeFn.bind(this))\n }\n utils.redirectToString(handler.get, nativeFn)\n }\n\n if (handlerGetterSetter.set !== undefined) {\n const nativeFn = ownPropertyDescriptor.set\n handler.set = function(newValue) {\n handlerGetterSetter.set.call(this, newValue, nativeFn.bind(this))\n }\n utils.redirectToString(handler.set, nativeFn)\n }\n\n Object.defineProperty(obj, propName, handler)\n}",mockWithProxy:"(obj, propName, pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n\n utils.replaceProperty(obj, propName, { value: proxyObj })\n utils.patchToString(proxyObj)\n\n return true\n}",createProxy:"(pseudoTarget, handler) => {\n const proxyObj = new Proxy(pseudoTarget, utils.stripProxyFromErrors(handler))\n utils.patchToString(proxyObj)\n\n return proxyObj\n}",splitObjPath:"objPath => ({\n // Remove last dot entry (property) ==> `HTMLMediaElement.prototype`\n objName: objPath.split('.').slice(0, -1).join('.'),\n // Extract last dot entry ==> `canPlayType`\n propName: objPath.split('.').slice(-1)[0]\n})",replaceObjPathWithProxy:"(objPath, handler) => {\n const { objName, propName } = utils.splitObjPath(objPath)\n const obj = eval(objName) // eslint-disable-line no-eval\n return utils.replaceWithProxy(obj, propName, handler)\n}",execRecursively:"(obj = {}, typeFilter = [], fn) => {\n function recurse(obj) {\n for (const key in obj) {\n if (obj[key] === undefined) {\n continue\n }\n if (obj[key] && typeof obj[key] === 'object') {\n recurse(obj[key])\n } else {\n if (obj[key] && typeFilter.includes(typeof obj[key])) {\n fn.call(this, obj[key])\n }\n }\n }\n }\n recurse(obj)\n return obj\n}",stringifyFns:"(fnObj = { hello: () => 'world' }) => {\n // Object.fromEntries() ponyfill (in 6 lines) - supported only in Node v12+, modern browsers are fine\n // https://github.com/feross/fromentries\n function fromEntries(iterable) {\n return [...iterable].reduce((obj, [key, val]) => {\n obj[key] = val\n return obj\n }, {})\n }\n return (Object.fromEntries || fromEntries)(\n Object.entries(fnObj)\n .filter(([key, value]) => typeof value === 'function')\n .map(([key, value]) => [key, value.toString()]) // eslint-disable-line no-eval\n )\n}",materializeFns:"(fnStrObj = { hello: \"() => 'world'\" }) => {\n return Object.fromEntries(\n Object.entries(fnStrObj).map(([key, value]) => {\n if (value.startsWith('function')) {\n // some trickery is needed to make oldschool functions work :-)\n return [key, eval(`() => ${value}`)()] // eslint-disable-line no-eval\n } else {\n // arrow functions just work\n return [key, eval(value)] // eslint-disable-line no-eval\n }\n })\n )\n}",makeHandler:"() => ({\n // Used by simple `navigator` getter evasions\n getterValue: value => ({\n apply(target, ctx, args) {\n // Let's fetch the value first, to trigger and escalate potential errors\n // Illegal invocations like `navigator.__proto__.vendor` will throw here\n utils.cache.Reflect.apply(...arguments)\n return value\n }\n })\n})",arrayEquals:"(array1, array2) => {\n if (array1.length !== array2.length) {\n return false\n }\n for (let i = 0; i < array1.length; ++i) {\n if (array1[i] !== array2[i]) {\n return false\n }\n }\n return true\n}",memoize:"fn => {\n const cache = []\n return function(...args) {\n if (!cache.some(c => utils.arrayEquals(c.key, args))) {\n cache.push({ key: args, value: fn.apply(this, args) })\n }\n return cache.find(c => utils.arrayEquals(c.key, args)).value\n }\n}"},_mainFunction:"(utils, opts) => {\n try {\n // Adds a contentWindow proxy to the provided iframe element\n const addContentWindowProxy = iframe => {\n const contentWindowProxy = {\n get(target, key) {\n // Now to the interesting part:\n // We actually make this thing behave like a regular iframe window,\n // by intercepting calls to e.g. `.self` and redirect it to the correct thing. :)\n // That makes it possible for these assertions to be correct:\n // iframe.contentWindow.self === window.top // must be false\n if (key === 'self') {\n return this\n }\n // iframe.contentWindow.frameElement === iframe // must be true\n if (key === 'frameElement') {\n return iframe\n }\n // Intercept iframe.contentWindow[0] to hide the property 0 added by the proxy.\n if (key === '0') {\n return undefined\n }\n return Reflect.get(target, key)\n }\n }\n\n if (!iframe.contentWindow) {\n const proxy = new Proxy(window, contentWindowProxy)\n Object.defineProperty(iframe, 'contentWindow', {\n get() {\n return proxy\n },\n set(newValue) {\n return newValue // contentWindow is immutable\n },\n enumerable: true,\n configurable: false\n })\n }\n }\n\n // Handles iframe element creation, augments `srcdoc` property so we can intercept further\n const handleIframeCreation = (target, thisArg, args) => {\n const iframe = target.apply(thisArg, args)\n\n // We need to keep the originals around\n const _iframe = iframe\n const _srcdoc = _iframe.srcdoc\n\n // Add hook for the srcdoc property\n // We need to be very surgical here to not break other iframes by accident\n Object.defineProperty(iframe, 'srcdoc', {\n configurable: true, // Important, so we can reset this later\n get: function() {\n return _srcdoc\n },\n set: function(newValue) {\n addContentWindowProxy(this)\n // Reset property, the hook is only needed once\n Object.defineProperty(iframe, 'srcdoc', {\n configurable: false,\n writable: false,\n value: _srcdoc\n })\n _iframe.srcdoc = newValue\n }\n })\n return iframe\n }\n\n // Adds a hook to intercept iframe creation events\n const addIframeCreationSniffer = () => {\n /* global document */\n const createElementHandler = {\n // Make toString() native\n get(target, key) {\n return Reflect.get(target, key)\n },\n apply: function(target, thisArg, args) {\n const isIframe =\n args && args.length && `${args[0]}`.toLowerCase() === 'iframe'\n if (!isIframe) {\n // Everything as usual\n return target.apply(thisArg, args)\n } else {\n return handleIframeCreation(target, thisArg, args)\n }\n }\n }\n // All this just due to iframes with srcdoc bug\n utils.replaceWithProxy(\n document,\n 'createElement',\n createElementHandler\n )\n }\n\n // Let's go\n addIframeCreationSniffer()\n } catch (err) {\n // console.warn(err)\n }\n }",_args:[]}); \ No newline at end of file diff --git a/Extension/manifest_v3/package.json b/Extension/manifest_v3/package.json index 0420305..ac4a644 100644 --- a/Extension/manifest_v3/package.json +++ b/Extension/manifest_v3/package.json @@ -1,51 +1,51 @@ { - "name": "EasySpider", - "version": "0.3.3", - "type": "module", - "scripts": { - "build": "rollup -c", - "dev": "rollup -c -w", - "crx": "crx3", - "package": "node package.js" - }, - "license": "GPL-3.0", - "dependencies": { - "crx": "^5.0.1", - "crx3": "^1.1.3", - "dotenv": "^16.0.0", - "jquery": "^3.6.4", - "rollup-plugin-alias": "^2.2.0", - "rollup-plugin-css-only": "^3.1.0", - "rollup-plugin-import-css": "^3.0.3", - "rollup-plugin-vue": "^6.0.0", - "vue": "^2.7.14", - "vue-template-compiler": "^2.7.14", - "webextension-polyfill": "^0.7.0", - "webextension-polyfill-ts": "^0.22.0" - }, - "devDependencies": { - "@rollup/plugin-alias": "^3.1.1", - "@rollup/plugin-commonjs": "^17.0.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^11.0.1", - "@rollup/plugin-replace": "^2.3.4", - "@types/chrome": "0.0.164", - "@types/fs-extra": "^9.0.13", - "@types/node": "^16.11.10", - "@vitejs/plugin-vue": "^1.9.3", - "esno": "^0.12.1", - "firebase": "^9.18.0", - "fs-extra": "^10.0.0", - "npm-run-all": "^4.1.5", - "rimraf": "^3.0.2", - "rollup": "^2.38.5", - "rollup-plugin-chrome-extension": "^3.6.12", - "rollup-plugin-empty-dir": "^1.0.4", - "rollup-plugin-inject-process-env": "^1.3.1", - "rollup-plugin-postcss": "^4.0.2", - "rollup-plugin-typescript2": "^0.31.0", - "rollup-plugin-vue2": "^0.8.1", - "rollup-plugin-zip": "^1.0.1", - "typescript": "^4.4.3" - } -} + "name": "EasySpider", + "version": "0.3.3", + "type": "module", + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "crx": "crx3", + "package": "node package.js" + }, + "license": "GPL-3.0", + "dependencies": { + "crx": "^5.0.1", + "crx3": "^1.1.3", + "dotenv": "^16.0.0", + "jquery": "^3.6.4", + "rollup-plugin-alias": "^2.2.0", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-import-css": "^3.0.3", + "rollup-plugin-vue": "^6.0.0", + "vue": "^2.7.14", + "vue-template-compiler": "^2.7.14", + "webextension-polyfill": "^0.7.0", + "webextension-polyfill-ts": "^0.22.0" + }, + "devDependencies": { + "@rollup/plugin-alias": "^3.1.1", + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^11.0.1", + "@rollup/plugin-replace": "^2.3.4", + "@types/chrome": "0.0.164", + "@types/fs-extra": "^9.0.13", + "@types/node": "^16.11.10", + "@vitejs/plugin-vue": "^1.9.3", + "esno": "^0.12.1", + "firebase": "^9.18.0", + "fs-extra": "^10.0.0", + "npm-run-all": "^4.1.5", + "rimraf": "^3.0.2", + "rollup": "^2.38.5", + "rollup-plugin-chrome-extension": "^3.6.12", + "rollup-plugin-empty-dir": "^1.0.4", + "rollup-plugin-inject-process-env": "^1.3.1", + "rollup-plugin-postcss": "^4.0.2", + "rollup-plugin-typescript2": "^0.31.0", + "rollup-plugin-vue2": "^0.8.1", + "rollup-plugin-zip": "^1.0.1", + "typescript": "^4.4.3" + } +} \ No newline at end of file diff --git a/Extension/manifest_v3/src/manifest.json b/Extension/manifest_v3/src/manifest.json index d413ac3..e2a1ab8 100644 --- a/Extension/manifest_v3/src/manifest.json +++ b/Extension/manifest_v3/src/manifest.json @@ -1,48 +1,57 @@ { - "name": "EasySpider", - "version": "0.3.3", - "description": "EasySpider's chrome extension", - "author": "Naibo Wang", - "manifest_version": 3, - "action": { - "default_icon": { - "16": "assets/icon-16.png", - "19": "assets/icon-19.png", - "38": "assets/icon-38.png", - "128": "assets/icon-128.png" + "name": "EasySpider", + "version": "0.3.3", + "description": "EasySpider's chrome extension", + "author": "Naibo Wang", + "manifest_version": 3, + "action": { + "default_icon": { + "16": "assets/icon-16.png", + "19": "assets/icon-19.png", + "38": "assets/icon-38.png", + "128": "assets/icon-128.png" + }, + "default_title": "EasySpider" }, - "default_title": "EasySpider" - }, - "icons": { - "16": "assets/icon-16.png", - "38": "assets/icon-38.png", - "128": "assets/icon-128.png" - }, - "background": { - "service_worker": "background.ts" - }, - "content_scripts": [ - { - "matches": [ - "http://*/*", - "https://*/*" - ], - "css": ["style/toolkit.css"], - "js": ["content-scripts/main.js"], - "run_at": "document_end", - "all_frames": true - } - ], - "web_accessible_resources": [ - { - "resources": [ "*/*.js" ], - "matches": [ - "http://*/*", - "https://*/*" - ] - } - ], - "permissions": [ - "identity", "storage", "tabs","scripting" - ] -} + "icons": { + "16": "assets/icon-16.png", + "38": "assets/icon-38.png", + "128": "assets/icon-128.png" + }, + "background": { + "service_worker": "background.ts" + }, + "content_scripts": [ + { + "matches": [ + "http://*/*", + "https://*/*" + ], + "css": [ + "style/toolkit.css" + ], + "js": [ + "content-scripts/main.js" + ], + "run_at": "document_end", + "all_frames": true + } + ], + "web_accessible_resources": [ + { + "resources": [ + "*/*.js" + ], + "matches": [ + "http://*/*", + "https://*/*" + ] + } + ], + "permissions": [ + "identity", + "storage", + "tabs", + "scripting" + ] +} \ No newline at end of file