htmlunit抓取动态网页(HtmlUnit在多线程环境下怎么使用才能避免网页抓取失败的问题)

优采云 发布时间: 2021-11-21 13:03

  htmlunit抓取动态网页(HtmlUnit在多线程环境下怎么使用才能避免网页抓取失败的问题)

  如何在多线程环境下使用HtmlUnit避免网页爬取失败的问题。我们来谈谈这个问题的解决方案。

  这个问题的原因其实很简单。例如,线程 A 正在使用 WebClient 对象来获取网页。在整个抓取过程结束之前,当前线程被 CPU 挂起,所以线程 B 被激活,然后 B 使用 A 使用的 WebClient 对象正在做其他网页抓取工作,那么此时 WebCLient 对象将清除未完成的工作留下的数据,等等,共享一个WebClient的线程越多,出现问题的频率就越高。丢失网页的概率更高。但其实这个问题并不难解决,它的解决方案也有广泛的适用性:不管是什么对象,在多线程环境中遇到资源共享问题时,通常有两种解决方案,一种是使用对于 JDK1.2 之后的 ThreadLocal 对象,

  早在JDK1.2 版本中就提供的java.lang.ThreadLocal 和ThreadLocal 为解决多线程程序的并发问题提供了新思路。使用这个工具类可以写得非常简洁漂亮。多线程程序。其原理是为每个线程保存一个局部变量的副本,以确保该变量不会与其他线程共享——这是一种保守但有效的方法。本文不是要介绍ThreadLocal的用法(具体用法请参考百度百科),而是要使用ThreadLocal解决多线程环境下HtmlUnit的WebClient对象的共享问题。

  请看如何使用ThreadLocal对象解决以上问题:

  package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.BrowserVersion;import com.gargoylesoftware.htmlunit.WebClient;/**

*

* @author Shenghany

* @date 2013-5-27

*/publicclassThreadLocalClientFactory{

//单例工厂模式privatefinalstaticThreadLocalClientFactory instance =newThreadLocalClientFactory();//线程的本地实例存储器,用于存储WebClient实例privateThreadLocal clientThreadLocal;/**

* 构造方法,初始时线程的本地变量存储器

*/publicThreadLocalClientFactory(){

clientThreadLocal =newThreadLocal();}/**

* 获取工厂实例

* @return 工厂实例

*/publicstaticThreadLocalClientFactory getInstance(){

return instance;}/**

* 获取一个模拟FireFox3.6版本的WebClient实例

* @return 模拟FireFox3.6版本的WebClient实例

*/publicWebClient getClient(){

WebClient client =null;/**

* 如果当前线程已有WebClient实例,则直接返回该实例

* 否则重新创建一个WebClient实例并存储于当前线程的本地变量存储器

*/if((client = clientThreadLocal.get())==null){

client =newWebClient(BrowserVersion.FIREFOX_3_6);

client.setCssEnabled(false);

client.setJavaScriptEnabled(false);

clientThreadLocal.set(client);System.out.println("为线程 [ "+Thread.currentThread().getName()+" ] 创建新的WebClient实例!");}else{

System.out.println("线程 [ "+Thread.currentThread().getName()+" ] 已有WebClient实例,直接使用. . .");}return client;}}

  测试代码:

<p>package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.WebClient;import com.gargoylesoftware.htmlunit.html.HtmlPage;/**

*

* @author Shenghany

* @date 2013-5-27

*/publicclassThreadLocalHtmlUnitTester{

/**

* 获取目标页面,并打印网页标题

* @param url 目标页面地址

*/publicstaticvoid getPage(String url){

//从工厂中获取一个WebClient实例WebClient client =ThreadLocalClientFactory.getInstance().getClient();try{

//抓取网页HtmlPage page =(HtmlPage)client.getPage(url);//打印当前线程名称及网页标题System.out.println(Thread.currentThread().getName()+" [ "+ url +" ] : "+ page.getTitleText());}catch(Exception e){

e.printStackTrace();}}/**

* 测试程序执行入口

* @param s

*/publicstaticvoid main(String[] s){

//文章编号int postId =50;//目标网页的部分内容String http ="http://www.yshjava.cn/post/4";/**

* 共16篇文章,每个线程抓取两篇,共计将产生8个线程

*/for(int i = postId; i

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线