在Ruby环境中执行指定JavaScript代码并获取变量值
在Ruby环境中执行JavaScript并提取u、u2变量值的方案
我来帮你搞定这个问题——在Ruby里跑这段JS并拿到u、u2的取值其实不难,分两种情况处理,看你的需求:
方案一:只提取u、u2变量值(最简便)
这段JS里的u、u2是直接赋值的字符串,和后面的DOM操作、定时器逻辑完全无关,所以我们可以只保留变量定义部分,修正语法错误后直接执行。
步骤1:修正原JS的语法错误
原代码里的字符串没有用引号包裹,而且&是HTML实体,在JS里要换成&,修正后的代码如下:
var u = "http://track.fk"; var u2 = "g.tv/2grc4?track=pub3878f5a9bae34c50a9f3ab0b59e1022e&pubid=8afa71db&aff_sub=pub3878f5a9bae34c50a9f3ab0b59e1022e";
步骤2:用Ruby的ExecJS执行代码
ExecJS是Ruby里调用JS引擎的常用库,先安装依赖:
gem install execjs
然后编写Ruby代码提取变量:
require 'execjs' # 修正后的JS代码,返回包含变量的对象 js_code = <<~JS var u = "http://track.fk"; var u2 = "g.tv/2grc4?track=pub3878f5a9bae34c50a9f3ab0b59e1022e&pubid=8afa71db&aff_sub=pub3878f5a9bae34c50a9f3ab0b59e1022e"; { u: u, u2: u2 } JS # 执行JS并获取结果 result = ExecJS.eval(js_code) # 输出变量值 puts "u的取值: #{result['u']}" puts "u2的取值: #{result['u2']}"
运行这段Ruby代码,就能直接拿到u和u2的取值:
u:http://track.fku2:g.tv/2grc4?track=pub3878f5a9bae34c50a9f3ab0b59e1022e&pubid=8afa71db&aff_sub=pub3878f5a9bae34c50a9f3ab0b59e1022e
方案二:完整执行所有JS代码(含DOM操作)
如果你需要完整执行包括定时器、DOM修改在内的所有逻辑,就得模拟浏览器的DOM环境,这里用mini_racer(更强大的Ruby-JS交互库)配合手动模拟DOM对象:
步骤1:安装依赖
gem install mini_racer
步骤2:编写Ruby代码
require 'mini_racer' # 完整修正后的JS代码,加上模拟的DOM对象 full_js_code = <<~JS var u = "http://track.fk"; var u2 = "g.tv/2grc4?track=pub3878f5a9bae34c50a9f3ab0b59e1022e&pubid=8afa71db&aff_sub=pub3878f5a9bae34c50a9f3ab0b59e1022e"; // 模拟浏览器的document对象,满足代码里的DOM操作需求 var document = { getElementById: function(id) { return { href: '' }; // 模拟一个a标签元素 }, getElementsByTagName: function(tag) { return [{ appendChild: function() {} }]; // 模拟head元素 }, createElement: function(tag) { return {}; // 模拟meta元素 } }; var link = document.getElementById("click"); setTimeout(function() { link.href = u+u2; }, 333); setTimeout(function() { var meta = document.createElement('meta'); meta.httpEquiv = 'refresh'; meta.content = '1;'+u+u2; document.getElementsByTagName('head')[0].appendChild(meta); }, 333); // 返回需要的变量 { u: u, u2: u2, initialLinkHref: link.href } JS # 创建JS上下文并执行代码 context = MiniRacer::Context.new result = context.eval(full_js_code) puts "u的取值: #{result['u']}" puts "u2的取值: #{result['u2']}" puts "初始link.href: #{result['initialLinkHref']}"
注意:因为setTimeout是异步操作,同步执行代码时拿不到定时器修改后的link.href,如果需要获取异步后的结果,得额外处理JS的异步逻辑(比如用Promise或者手动触发定时器回调)。
内容的提问来源于stack exchange,提问作者petspanda D
相关产品推荐
相关产品推荐

