htmlunit爬虫案例

过去有一段时间了,记录一下曾经参与过的爬虫项目。

一个main方法,开两个线程,一个收集需要执行爬取的任务,一个执行爬取。

//数据采集:判断是否启动采集线程
			String isStartDataSpiderTask = SystemProperties.getContextProperty("data.spider.task");
			if(isStartDataSpiderTask != null && isStartDataSpiderTask.equalsIgnoreCase("true")){
//				DataSpiderTask dataSpiderTask = new DataSpiderTask();
//				dataSpiderTask.start();
				
				DataKpiPullQueueThread pullThread = new DataKpiPullQueueThread();
				pullThread.start();
				LogCvt.info("已启动数据采集-采集线程,任务队列 :" + RedisConstent.DATA_SPIDER_QUEUE_REDISKEY);
				
				//指标监控线程
				DataMonitorTask dataMonitorTask = new DataMonitorTask();
				dataMonitorTask.start();
				LogCvt.info("已启动数据采集-指标监控线程,任务队列 :" + RedisConstent.DATA_KPI_MONITOR_REDISKEY2);
			}
			
			//数据采集:定时任务收集线程
			String isStartDataSpiderCollectTask = SystemProperties.getContextProperty("data.spider.collect.task");
			if(isStartDataSpiderCollectTask != null && isStartDataSpiderCollectTask.equalsIgnoreCase("true")){
//				DataSpiderCollectTask task = new DataSpiderCollectTask();
//				task.start();
				
				DataKpiPushTaskQueueThread pushTaskThread = new DataKpiPushTaskQueueThread();
				pushTaskThread.start();
				
				LogCvt.info("已启动数据采集-定时任务收集线程,任务队列 :" + RedisConstent.DATA_SPIDER_QUEUE_REDISKEY_TASK);
			}

收集的线程我就不写了,无非就是从数据库篓出要执行的记录,扔到redis里去,等着爬取的线程去redis里取。

着重写爬取线程。

爬取线程里放一个线程池,这个线程池具体开几个爬取线程,看自己情况。

当然,实际执行爬取任务的线程是这个线程池里的线程。

爬取线程放入线程池。

爬取线程里当然就要开始用到今天的主角htmlunit。

htmlunit的基本用法参考这篇博客

要爬取你想要的东西,得需要多看看xpath及正则。

这里再讲讲当时我们用htmlunit出现的一个比较典型的问题,内存泄漏:

1,当时是没有关闭页面这段代码的。先解释下这个webClient,它就相当于打开了一个浏览器。因为当时前期需求方给的指标量是比较少的,你一次在浏览器中开几十个页面是没有问题的。但是到了后期,指标量陡然上升,成百上千个,你可能就需要打开成百上千个页面,这个时候就很可能对你的内存造成比较大的压力,你会感觉越来越卡,到最后可能程序就卡死了。

2,接下来这个问题,当时就发生在给我的一批指标当中,这一批指标我记得大概有几千个指标,因为抓取的是表格,每个表格有几十行,当时的代码逻辑是一行就会生成一个对象,为了提高爬取效率,这些行对象会一直保存直到这条线程采集完所有指标。所以当时就会有上万级的对象存在于内存中,我是亲自体验到程序一点点卡死的感觉。后面经过优化,最主要的一点就是把指标根据url分组采集了。简单来说就是把人家列表页面的a标签链接分组采集,一个a标签链接里面得表格里的一个单元格是一个指标。每采集下一个a标签,就把上一个a标签缓存的表格数据清掉,这样就不会造成内存的压力了。

猜你喜欢

转载自blog.csdn.net/suchengbin3433/article/details/86513240