网页抓取之新方法 (在java程序中使用jQuery)

    你想要的任何信息,基本上在互联网上存在了,问题是如何把它们整理成你所需要的,比如在某个行业网站上抓取所有相关公司的的名字,联系电话,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等。 代码如下,

 

package stony.zhang.scrape;


import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

/**
 * @author MyBeautiful
 * @Emal: zhangyu0182@sina.com
 * @date Mar 7, 2012
 */
public class RhinoScaper {
	private String url;
	private String jsFile;

	private Context cx;
	private Scriptable scope;

	public String getUrl() {
		return url;
	}

	public String getJsFile() {
		return jsFile;
	}

	public void setUrl(String url) {
		this.url = url;
		putObject("url", url);
	}

	public void setJsFile(String jsFile) {
		this.jsFile = jsFile;
	}

	public void init() {
		cx = ContextFactory.getGlobal().enterContext();
		scope = cx.initStandardObjects(null);
		cx.setOptimizationLevel(-1);
		cx.setLanguageVersion(Context.VERSION_1_5);

		String[] file = { "./lib/env.rhino.1.2.js", "./lib/jquery.js" };
		for (String f : file) {
			evaluateJs(f);
		}
		
		try {
			ScriptableObject.defineClass(scope, ExtendUtil.class);
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		} catch (InstantiationException e1) {
			e1.printStackTrace();
		} catch (InvocationTargetException e1) {
			e1.printStackTrace();
		}
		ExtendUtil util = (ExtendUtil) cx.newObject(scope, "util");
		scope.put("util", scope, util);
	}

	protected void evaluateJs(String f) {
		try {
			FileReader in = null;
			in = new FileReader(f);
			cx.evaluateReader(scope, in, f, 1, null);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}

	public void putObject(String name, Object o) {
		scope.put(name, scope, o);
	}

	public void run() {
		evaluateJs(this.jsFile);
	}
}

 

   测试代码:

 

package stony.zhang.scrape;

import java.util.HashMap;
import java.util.Map;

import junit.framework.TestCase;

public class RhinoScaperTest extends TestCase {

	public RhinoScaperTest(String name) {
		super(name);
	}

	public void testRun() {
		RhinoScaper rs = new RhinoScaper();
		rs.init();
		rs.setUrl("http://www.baidu.com");
		rs.setJsFile("test.js");
//		Map<String, String> o = new HashMap<String, String>();
//		rs.putObject("result", o);
		rs.run();
//		System.out.println(o.get("imgurl"));
	}

}

 

 

    test.js文件,如下

 

$.ajax({
  url: "http://www.baidu.com",
  context: document.body,
  success: function(data){
 //   util.log(data);
    
    var result =parseHtml(data);
    
    var $v= jQuery(result);
 //   util.log(result);
    $v.find('#u a').each(function(index) {
         util.log(index + ': ' + $(this).attr("href"));
  //        arr.add($(this).attr("href"));
    });
  }
});


 function parseHtml(html) {
       //Create an iFrame object that will be used to render the HTML in order to get the DOM objects
        //created - this is a far quicker way of achieving the HTML to DOM conversion than trying
        //to transform the HTML objects one-by-one
         var oIframe = document.createElement('iframe');
     //Hide the iFrame from view
         oIframe.style.display = 'none';
         if (document.body)
            document.body.appendChild(oIframe);
        else
            document.documentElement.appendChild(oIframe);
        
        //Open the iFrame DOM object and write in our HTML
        oIframe.contentDocument.open();
        oIframe.contentDocument.write(html);
        oIframe.contentDocument.close();
    
        //Return the document body object containing the HTML that was just
        //added to the iFrame as DOM objects
        var oBody = oIframe.contentDocument.body;
    
        //TODO: Remove the iFrame object created to cleanup the DOM
    
        return oBody;
    }

 

 

    我们执行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抓取网页是可行的.

 

 

----------------------------------------------------------------------

张瑜,Mybeautiful , zhangyu0182@sina.com

 

推荐阅读,

Java学习这七年     如何阅读源代码     我应该做的更差吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值