在java程序中使用jQuery抓取网页的新方法(java调用js解析引擎)

转载自:http://www.open-open.com/lib/view/open1331187174202.html

    你想要的任何信息,基本上在互联网上存在了,问题是如何把它们整理成你所需要的,比如在某个行业网站上抓取所有相关公司的的名字,联系电话,Email等,然后存到Excel里面做分析。网页信息抓取变得原来越有用了。


    一般传统的网页,web服务器直接返回Html,这类网页很好抓,不管是用何种方式,只要得到html页面,然后做Dom解析就可以了。但对于需要Javascript生成的网页,就不那么容易了。张瑜 目前也没有找到好办法解决此问题。各位有抓javascript网页经验的朋友,欢迎指点。


    所以今天要谈的还是传统html网页的信息抓取。虽然前面说了,没有技术难度,但是是否能有相对更容易的方法呢? 用过jQuery等js框架的朋友,可能都会觉得javascript貌似抓取网页信息的天然助手,而且其出生就是为了网页解析而存在的。当然现在有更多的应用了,如Server端的javascript应用,NodeJs.


    如果能在我们的应用程序,如java程序中,能使用jQuery去抓网页,绝对是件激动人心的事情 。确实有现成的解决方案,一个Javascript引擎,一个能支撑jQuery运行的环境就可以了。


    工具 : java, Rhino, envJs. 其中 Rhino是Mozzila提供的开源Javascript引擎,envJs是一个模拟浏览器额环境,如Window等。 代码如下,

01 package stony.zhang.scrape;
02  
03  
04 import java.io.FileNotFoundException;
05 import java.io.FileReader;
06 import java.io.IOException;
07 import java.lang.reflect.InvocationTargetException;
08  
09 import org.mozilla.javascript.Context;
10 import org.mozilla.javascript.ContextFactory;
11 import org.mozilla.javascript.Scriptable;
12 import org.mozilla.javascript.ScriptableObject;
13  
14 /**
15  * @author MyBeautiful
16  * @Emal: zhangyu0182@sina.com
17  * @date Mar 7, 2012
18  */
19 public class RhinoScaper {
20     private String url;
21     private String jsFile;
22  
23     private Context cx;
24     private Scriptable scope;
25  
26     public String getUrl() {
27         return url;
28     }
29  
30     public String getJsFile() {
31         return jsFile;
32     }
33  
34     public void setUrl(String url) {
35         this.url = url;
36         putObject("url", url);
37     }
38  
39     public void setJsFile(String jsFile) {
40         this.jsFile = jsFile;
41     }
42  
43     public void init() {
44         cx = ContextFactory.getGlobal().enterContext();
45         scope = cx.initStandardObjects(null);
46         cx.setOptimizationLevel(-1);
47         cx.setLanguageVersion(Context.VERSION_1_5);
48  
49         String[] file = { "./lib/env.rhino.1.2.js""./lib/jquery.js" };
50         for (String f : file) {
51             evaluateJs(f);
52         }
53          
54         try {
55             ScriptableObject.defineClass(scope, ExtendUtil.class);
56         catch (IllegalAccessException e1) {
57             e1.printStackTrace();
58         catch (InstantiationException e1) {
59             e1.printStackTrace();
60         catch (InvocationTargetException e1) {
61             e1.printStackTrace();
62         }
63         ExtendUtil util = (ExtendUtil) cx.newObject(scope, "util");
64         scope.put("util", scope, util);
65     }
66  
67     protected void evaluateJs(String f) {
68         try {
69             FileReader in = null;
70             in = new FileReader(f);
71             cx.evaluateReader(scope, in, f, 1null);
72         catch (FileNotFoundException e1) {
73             e1.printStackTrace();
74         catch (IOException e1) {
75             e1.printStackTrace();
76         }
77     }
78  
79     public void putObject(String name, Object o) {
80         scope.put(name, scope, o);
81     }
82  
83     public void run() {
84         evaluateJs(this.jsFile);
85     }
86 }
   测试代码:
01 package stony.zhang.scrape;
02  
03 import java.util.HashMap;
04 import java.util.Map;
05  
06 import junit.framework.TestCase;
07  
08 public class RhinoScaperTest extends TestCase {
09  
10     public RhinoScaperTest(String name) {
11         super(name);
12     }
13  
14     public void testRun() {
15         RhinoScaper rs = new RhinoScaper();
16         rs.init();
17         rs.setUrl("http://www.baidu.com");
18         rs.setJsFile("test.js");
19 //      Map<String, String> o = new HashMap<String, String>();
20 //      rs.putObject("result", o);
21         rs.run();
22 //      System.out.println(o.get("imgurl"));
23     }
24  
25 }
    test.js文件,如下
01 $.ajax({
02   url: "http://www.baidu.com",
03   context: document.body,
04   success: function(data){
05  //   util.log(data);
06      
07     var result =parseHtml(data);
08      
09     var $v= jQuery(result);
10  //   util.log(result);
11     $v.find('#u a').each(function(index) {
12          util.log(index + ': ' + $(this).attr("href"));
13   //        arr.add($(this).attr("href"));
14     });
15   }
16 });
17  
18  
19  function parseHtml(html) {
20        //Create an iFrame object that will be used to render the HTML in order to get the DOM objects
21         //created - this is a far quicker way of achieving the HTML to DOM conversion than trying
22         //to transform the HTML objects one-by-one
23          var oIframe = document.createElement('iframe');
24      //Hide the iFrame from view
25          oIframe.style.display = 'none';
26          if (document.body)
27             document.body.appendChild(oIframe);
28         else
29             document.documentElement.appendChild(oIframe);
30          
31         //Open the iFrame DOM object and write in our HTML
32         oIframe.contentDocument.open();
33         oIframe.contentDocument.write(html);
34         oIframe.contentDocument.close();
35      
36         //Return the document body object containing the HTML that was just
37         //added to the iFrame as DOM objects
38         var oBody = oIframe.contentDocument.body;
39      
40         //TODO: Remove the iFrame object created to cleanup the DOM
41      
42         return oBody;
43     }
我们执行Unit Test,将会在控制台打印从网页上抓取的三个baidu的连接,

0: http://www.baidu.com/gaoji/preferences.html
1: http://passport.baidu.com/?login&tpl=mn
2: https://passport.baidu.com/?reg&tpl=mn

 

   测试成功,故证明在java程序中用jQuery抓取网页是可行的.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值