前几天帮某个人抓取某电商网站商品属性的,得到页面后需要解析一个<script>内的代码获得其中一个json对象的属性, 开始是想字符串截取呢,后来感觉不怎么好,就换成用java解析script了,感觉还行,其中有几个坑,在这里记录下,
对于一段js代码,java在解析时,需要补齐其中的空间变量,比如 var window={};
还有js中调用的函数,如果不关心的话,也需要按调用方式预先定义好,比如consloe.log();否则js片段缺少变量无法继续
对于你需要获取的数据,比如json串,最好还是写个js函数附在js片段后面来执行获取;
对于简单的工具函数也最好能抄过来定义好
每个变量,函数都需要以分号结尾,java这样的强类型遇到js这样的弱类型,错误提示简直不能看啊.(此处耗时1小时),因为 var a=function(){}; 这里最后缺少一个分号,提示各种错乱.
我需要解析的js如下:
1window.markPageStylesReady("e58dfbdc-9154-4482-aeb3-d1d32aa05195"); 2if (!window.pageParams) { 3 window.pageParams = {}; 4} 5window.pageParams["e58dfbdc-9154-4482-aeb3-d1d32aa05195"] = { 6 "browser_type": "unknown", 7 "contest": { 8 "product_rating": { 9 "rating": 5.0, 10 }, 11 "id": "5731b2460efe256073e4631e", 12 "remarket_tag": { 13 "name": "Hats" 14 }, 15 "commerce_product_info": { 16 "fbw_pending": 0, 17 "is_fulfill_by_wish": false, 18 "variations": [{ 19 "original_price": 1, 20 "shipping_price_country_code": "US", 21 "color": "Multicolor", 22 "variation_id": "573307b481e30f5ec28e3801", 23 "type": ["1"], 24 "size": [{ 25 "1": "1" 26 }], 27 "shipping": 1 28 }, { 29 "original_price": 1, 30 "color": "Multicolor", 31 "type": ["2"], 32 "size": [{ 33 "2": "2" 34 }], 35 "size_ordering": 0, 36 "variation_id": "123", 37 "shipping": 1 38 }], 39 "is_active_fbw_in_us": false, 40 }, 41 "contest_selected_picture": "0", 42 "num_bought": 0, 43 "is_expired": false, 44 "num_won": 0, 45 "external_url": "http:\/\/www.xxoo.com\/c\/5731b2460efe256073e4631e" 46 }, 47 "force_login_required": false 48}; 49// This parameter will get consumed by the page's script and used 50// to initialize the page correctly 51window.nextInitializePageId = 'e58dfbdc-9154-4482-aeb3-d1d32aa05195';
需要获取
window.pageParams['e58dfbdc-9154-4482-aeb3-d1d32aa05195'].contest.commerce_product_info.variations
这个json串,
为此找了个json2str函数,稍微写了点垃圾代码
然后用javax.script.ScriptEngine就搞定了:
代码如下:
1///file是就整个html文件 2Document doc = Jsoup.parse(file, "UTF-8"); 3 Elements ee = doc.getElementsByTag("script"); 4 String text = ""; 5 for ( Element e : ee ) { 6 String t = e.html(); 7 if ( t.indexOf("\"5731b2460efe256073e4631e\"") > 0 && t.indexOf("\"product_id\"") > 0 ) { 8 text = t; 9 } 10 } 11 if ( "".equals(text) ) return null; 12// System.out.println(text); 13 String strbef = ";var t=''; var window={ markPageStylesReady: function(a){t=a} } ; "; 14 String straft = ";function getv(){return window.pageParams[t].contest.commerce_product_info.variations ;}"; 15 String json2str = "function json2str(o) { " 16 +" var arr = []; " 17 +" var fmt = function(s) { " 18 +" if( typeof s == \"string\") {return \"\\\"\" + s + \"\\\"\" ;}" 19 +" if( typeof s == \"number\") {return \"\\\"\" + s + \"\\\"\";} " 20 +" if (typeof s == \"object\" ) { if( s != null) { return json2str(s);} } " 21 +" return s ;" 22 +" }; " 23 +" for (var i in o) {arr.push(\"\\\"\" + i + \"\\\":\" + fmt(o[i]));} " 24 +" return \"{\" + arr.join(\",\") + \"}\"; " 25 +"}; " 26 + " var o=getv(); " 27 + " function aa(){ return json2str(o);}; " ; 28 29 /*所有变量和函数都要有分号结尾..*/ 30 31 javax.script.ScriptEngineManager sem = new javax.script.ScriptEngineManager(); 32 javax.script.ScriptEngine engine = sem.getEngineByExtension("js"); 33 engine.eval(strbef + text + straft+json2str); 34 Invocable inv = (Invocable) engine; 35 Object obj = inv.invokeFunction("aa"); 36 JSONObject jsonobj = JSON.parseObject(obj.toString()); 37 System.out.println(jsonobj.getJSONObject("0").get("max_shipping_time"));
如期得到结果,good job!