巧用eval将抓取的外部JS加到UIXML的JS环境

nandy007
   2015-07-24 10:52:20发布  2016-12-16 16:54:37更新 0收藏, 2361浏览
ExMobi客户端技术
0

我们在使用页面抓取技术的时候,时常会遇到想要的数据在一个script标签里,而最先想到的办法就是正则(可以参考此贴http://bbs.exmobi.cn/thread-1678-1-1.html),然而,script的内容通常又是很复杂的,对正则能力有一定的要求,比如下面的一组树的展现:

我们也可以很清楚的在抓取到的数据中看到它是位于JS中的:


如果不用正则转换,我们还能怎么做呢?


我们注意观察,这棵树其实就是一个数组(Array对象),如果这些对象能够直接搬到我们的JS环境中运行,那我们不就很轻松的使用这个数组数据了吗?

感觉捡了个大便宜啊,但是问题来了:

1、这些JS怎么全部取出?

2、这些JS如何转换成UIXML里的JS环境?

问题1我想小伙伴们应该都有所思路了吧,通过xpath是最好不过的了。

那么问题2就是本帖重点要说的技术了,也就是eval

本次示例代码如下:

whatiseval.zip(0.18M 下载次数:78)

下面简单介绍下思路:

简单的说,eval可以执行一个字符串的内容,也就是说如果这个字符串写的是var str='var a=1;',执行eval(str)的结果就相当于定义了变量a,并给他赋值为1,在接下来的代码中你可以调用变量a而不会报undefined

这里有一篇eval的详解,不清楚的童鞋可以看下,http://bbs.exmobi.cn/thread-4407-1-1.html


所以,现在思路就很清晰了:

首先,我们需要在JSP中获取到需要加到uixml的JS环境的中的外部JS内容,请看下面的data.jsp代码:

<%-- ExMobi JSP文件,注释和取消快捷键统一为Ctrl / 多行注释为Ctrl Shift / --%>
<%@ page language="java" import="java.util.*"
 contentType="text/javascript; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/client/adapt.jsp"%>
<%
//这里在jsp目录准备了一个测试用的index.html页面,我们需要从index.html获取我们要的JS内容
String url = "http://" request.getRemoteHost() ":8001/process/service/whatiseval/index.html";
%>
<aa:http id="index" url="<%=url %>" mimetype="text/xml"></aa:http>
<%
//取出所需要的JS对象内容,并输出
String result = aa.xpath.xpath("//script[not(@src) and contains(text(), 'treedata')]", "index");
out.println(result);
%>

此JSP返回一个javascript(看content-type),具体的内容是通过xpath获取的(看result变量)。


其次,我们需要在uixml中发起一个ajax请求(只有ajax才能构造JS环境),在成功回调函数中对JSP返回的JS内容执行eval,从而将此内容加入到当前的uixml的JS环境中,代码如下:

var tree;
function doSuccess(data){
        //在回调函数中获取到JSP返回的JS内容的字符串
        var str = data.responseText;
        //放到try里只能避免数据相对分离开的,因为JS在报错之后后续的代码不会执行,而本例中的垃圾数据刚好在数据定义之后才出现,所以可以用try
        //否则一般需要在JSP中进行处理,把不干净的数据删掉,最终返回的是干净的JS数据
        try{
                eval(str);//对此字符串进行eval执行之后就相当于在duSuccess这个环境里有了抓取到的JS内容
        }catch(e){
                Log.i(e);
        }
        //此时将得到treedata这个变量,它是一个数组
        //这里利用exmobijs封装的tree对象来构建树,数据格式可以参考exmobijs对tree的说明
        var arr = createTreeArr(treedata);
        tree = $tree("tree");
        tree.load(arr);
}

function createTreeArr(treedata, pId){
        var arr = [];
        for(var i=0;i<treedata.length;i  ){
                var obj = {};
                var json = treedata[i];
                obj.id = json.id;
                obj.pId = pId||'tree';
                obj.text = json.caption;
                arr.push(obj);
                if(json.children){
arr = arr.concat(createTreeArr(json.children, json.id));
                }
        }
        return arr;
}

这样就完成了将外部的,最终的模拟器效果如下:

1

jt.png  (0.02M  下载次数:64次)

tree.png  (0.06M  下载次数:57次)

js.png  (0.02M  下载次数:58次)

下载APP
扫码下载栗子社区APP