首页 > 其他分享 >htmlunit设置支持js和 ajax

htmlunit设置支持js和 ajax

时间:2022-11-03 10:39:58浏览次数:48  
标签:endsize htmlunit value js ajax page webclient handletime


免责声明:不要拿爬虫在法律边缘试探

简单的说,就是进行如下设置:

webclient.getOptions().setUseInsecureSSL(true);
// 禁用css ,一般来说 css没啥用
webclient.getOptions().setCssEnabled(false);
webclient.getOptions().setThrowExceptionOnFailingStatusCode(false);
// 设置支持 js
webclient.getOptions().setJavaScriptEnabled(true);
// 不抛出异常
webclient.getOptions().setThrowExceptionOnScriptError(false);
webclient.getOptions().setDoNotTrackEnabled(true);
// 最好设置一下超时
webclient.getOptions().setTimeout(5*1000);
// 支持ajax
webclient.setAjaxController(new NicelyResynchronizingAjaxController());

如果简单的看,这样也就解决了,但是我们试着回想一下,当我们自己打开网页的时候是不是都得等半天(有一段时间,肯定不是半天),于是问题来了,如果我们直接写代码

HtmlPage page = webclient.getPage(url);

可以确定,如果是比较小的js操作,在你余下操作完成之前,js可能能够执行完成,如果是那种比较繁琐的js操作或者是ajax还需要去请求其他服务器的操作,多半在于你余下操作(例如解析html等)之前,js是无法执行完的,那么我们得到的就是不完成的网页。所以设置一个超时时间是很有必要的,也就是这样:

HtmlPage page = webclient.getPage(url);
// TODO: 2019/1/4 10秒钟是为了让js能够充分执行(特别是ajax)
webclient.waitForBackgroundJavaScript(10*1000);
webclient.setJavaScriptTimeout(5*1000);

将上诉代码放到项目中进行测试,我们可以发现可以得到结果了(这里只能说得到了结果,谁也不清楚正确的网页到底爬下来是怎么样的,这是为做一个通用的爬虫准备的,没人能够预测这些不同网站的网页里面的Js究竟会执行多久)。

于是,又出现了几个问题:
1、如何确定某类网站的js平均响应时间,一般来说,同种类型的网站(由于跟响应需求有关,有些网站没必要性能很好这个可以理解)可以算个js平均响应时间。这个时间用来设置 htmlunit设置支持js和 ajax_htmlunit
2、是否可以优化js 执行时间
3、如果每个页面都等待那么长时间(而且这种等待是必然每个页面都会等待),那么如果量比较大,比如爬取一千个不同的网站,该如何优化,使得整体的性能不至于非常差。

留坑:
1、第一个问题的本质是我该如何进行测试
2、第二个问题个人觉得应该从 htmlunit 选择浏览器,设置 js 引擎和 ajax 支持出发去优化
3、到第三个问题,是在前两个问题已经确定的情况下进行优化的,需要对遍历算法和线程池进行优化

第一个问题,我的解决办法是 写一个动态的方法来记录页面的加载时间,主要在数据库中存储这几个字段

字段名

字段含义

字段类型

url

网页地址

string

size

当前检查的网页大小

double

waittime

等待js的执行时间

double

netaffect

上一次结果是否受网络影响

int

maxsize

记录中页面最大是多大

double

作为维护的中间变量,然后每一次通过一定的算法自动调节等待的时间,也就是说,对于每一个页面动态的根据相关算法调整等待js的执行时间。代码例子如下:

@Override
public HtmlPage executeReq(double handletime) {
int time = 1;
ArrayList<String> cache = redisDao.getMultiValue(url);
double lastpagesize = 0.0*-1;
double lasthandletime = 1000;
double maxsize = 0.0*-1;
int affect = -1;
if (cache != null){
lastpagesize = Double.parseDouble(cache.get(0));
lasthandletime = Double.parseDouble(cache.get(1));
maxsize = Double.parseDouble(cache.get(2));
affect = Integer.parseInt(cache.get(3));
}
if (affect == 1){
handletime = handletime/2.0;
}
while (time <= 5) {
try {
HtmlPage page = webclient.getPage(url);
// TODO: 2019/1/4 线程休息五秒钟是为了让js能够充分执行(特别是ajax)
webclient.waitForBackgroundJavaScript((long) (handletime*1000));
webclient.setJavaScriptTimeout(5*1000);
// TODO: 2019/1/7 判断当前page大小与上一次page大小的关系,如果小于之前page的一半就重新尝试,并且保留最大的那一次
double pagesize = page.asXml().length();
if ((lastpagesize - 2*pagesize) < -1*0.0001){
endpage = pagesize>endsize?page:endpage;
endsize = Math.max(pagesize, endsize);
jiangeshijian = pagesize>endsize?handletime:jiangeshijian;
if (time < 5){
handletime = handletime + 1.0;
continue;
}
}else {
endpage = page;
endsize = pagesize;
jiangeshijian = handletime;
}
ArrayList<String> value = new ArrayList<String>();
String toredissize = "";
toredissize = toredissize + endsize;
String toredistime = "";
toredistime = toredistime + jiangeshijian;
value.add(toredissize);
value.add(toredistime);
if (maxsize < endsize){
value.add(toredissize);
}else {
String toredismaxsize = "" + maxsize;
value.add(toredismaxsize);
if (jiangeshijian > lasthandletime){
value.add("1");
}else {
value.add("0");
}
}
redisDao.setMultiValue(url,value);
return endpage;
} catch (IOException e) {
e.printStackTrace();
}
time++;
}
return null;
}

这里我将维护的信息放到redis里面的

关于第二个问题,我在咨询了技术大佬之后,他建议我用一个真正的爬虫来做,htmlunit 是一个比较好的模拟浏览器的框架,但是在爬虫方面算不上一个比较好的

关于第三个问题,尚没有解决


标签:endsize,htmlunit,value,js,ajax,page,webclient,handletime
From: https://blog.51cto.com/u_14196886/5819054

相关文章

  • 元素JS 完成 html 文件的生成 下载
    前端生成html字符串模板,并进行下载通过字符串拼接出完整的html文件使用Blob构造出一个Blob文件对象使用window.URL.createObjectURL将文件对象解析成url将......
  • 【c&c++】 cjson使用_Keil环境下Jansson解析库的使用——基于STM32F103
    前言之前我曾经写过几个JSON解析库的使用方法:Qt平台下使用QJson解析和构建JSON字符串使用cJSON库解析JSON使用cJSON库构建JSON对于嵌入式开发,比较常用的就是cJSON解析......
  • 【c&c++】[C++]使用Jansson生成与解析json字符串
    安装配置序列化与反序列化生成Json解析JsonJansson是一个用于解码、编码、操控JSON的C库:简单直观的API和数据模型没有依赖项完整的Unicode支持(UTF-8)安装 ......
  • 七牛云API的使用包括Ajax上传功能及凭证生成
    1.服务端(主要用于生成上传,删除,下载等凭证)引入Qiniu的Get包。包就叫Qiniu。//上传凭证//上传凭证:其余凭证类似的写法publicstringUpLoadToken()......
  • 富文本编辑器 quill.js 开发(二): 升级与表格功能
    前言在富文本编辑器场景中,表格是一种不可忽视的功能,但是在当前quill.js的正式版本(1.x)中,却不支持此功能所以本文承接上文链接,来讲述下quill.js升级到2.x......
  • JS
    1.简介JavaScript是脚本语言JavaScript是一种轻量级的编程语言JavaScript是可插入HTML页面的编程代码JavaScript插入HTML页面后,可由所有的现代浏览器执行2......
  • jsx的使用
    1.什么是jsxJSX是JavaScriptXML的简写,表示了在Javascript代码中写XML(HTML)格式的代码优势:声明式语法更加直观,与HTML结构相同,降低学习成本,提高开发效率。JSX是react的......
  • selenium-执行JS代码
    importtimefromwebdriver_helperimportwebdriver,get_webdriverfromselenium.webdriverimportchromefromselenium.webdriver.common.byimportBydriver=......
  • JAVAWeb - JSP标签
    一:EL 表达式获取数据执行运算获取web开发的常用的对象二:JSP标签<jsp:forwardpage="/jsptag2.jsp"><jsp:paramname="name"value="maming"></jsp:param>......
  • #yyds干货盘点#JS 解析 excel 文件
    JS解析excel文件分为如下几步:使用 ​​js​​ 解压缩 ​​excel​​ 文件获取到其中的 ​​sheet​​ 文件内容,然后将 ​​xml​​ 数据解析出来将数据转换成我们想......