htmlunit怎么获取javascript 弹出页面页面

13129人阅读
【java】(106)
上次我不是写了一个自动抓取博客访问量吗 () 可是昨天晚上我又运行的时候,发现不能用了。。
运行了几次 发现使用URLConnection 得到的网页源码和浏览器直接查看的不同。 URLConnection 使用IO流读取到的源码
只有积分 &没有访问量了
而使用浏览器访问 直接查看源码
这也就导致了我的程序不能用了 &需要更新了
想想原因 & 可能是幕后主使人把访问量放在了js里面 & 动态展示,而我使用URLConnection 访问的静态界面 &确确实实没有收到。
于是开始百度了 &百度过来 百度过去。。
发现了一个回复了三年还没有结贴的帖子
里面回复了好多方法 &发现有个htmlunit &于是就自己测试一下
发现真的可以。得到了js执行后的源码。
废话不说了。
public static void main(String[] args) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
// TODO Auto-generated method stub
WebClient wc=new WebClient(BrowserVersion.FIREFOX_24);
wc.setJavaScriptTimeout(5000);
wc.getOptions().setUseInsecureSSL(true);//接受任何主机连接 无论是否有有效证书
wc.getOptions().setJavaScriptEnabled(true);//设置支持javascript脚本
wc.getOptions().setCssEnabled(false);//禁用css支持
wc.getOptions().setThrowExceptionOnScriptError(false);//js运行错误时不抛出异常
wc.getOptions().setTimeout(100000);//设置连接超时时间
wc.getOptions().setDoNotTrackEnabled(false);
HtmlPage page=wc.getPage(&http://blog.csdn.net/su?viewmode=contents&);
String res=page.asText();
//处理源码
deal(res);
最后得到的源码如下:
其它的代码和&这篇文章相比几乎没变。如果不明白 可以去看一下 &这里就不再赘述了
执行后 &成功写入到txt文档
使用了htmlunit会弹出好多异常警告
加上这些代码 &就会消失了~
LogFactory.getFactory().setAttribute(&mons.logging.Log&,
&mons.logging.impl.NoOpLog&);
java.util.logging.Logger.getLogger(&com.gargoylesoftware.htmlunit&)
.setLevel(Level.OFF);
java.util.logging.Logger.getLogger(&mons.httpclient&)
.setLevel(Level.OFF);
由于我们在这里 引入了htmlunit 的jar包 &.那么再用上次的脚本批量处理 就行不通了 ~
而且要引入的jar包也不是一个 &是多个 &所以要批量处理了
首先我们要把所有要用的jar包 使用-cp命令导入。
可是htmlunit的jar包太多了 &所以想到一个方法 &使用for循环遍历htmlunit文件夹里面的jar文件 &将其处理为一个字符串 然后再使用-cp命令 全部代码如下
setlocal enabledelayedexpansion
::定义一个字符串
::遍历htmlunit文件夹
for /f &delims=& %%a in ('dir /b &E:\lib\htmlunit-2.14-bin\lib\*.jar&') do (
set &str=!str!E:\lib\htmlunit-2.14-bin\lib\%%a;&
javac -cp .;%str% AutoMarkBlogView.java
java -cp .;%str% AutoMarkBlogView
pause运行结果如下:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1281987次
积分:19643
积分:19643
排名:第465名
原创:594篇
转载:17篇
评论:345条
点图片联系我
点图片联系我
文章:49篇
阅读:129372
文章:234篇
阅读:534640
文章:126篇
阅读:304991
文章:16篇
阅读:22622
(3)(5)(5)(17)(52)(17)(4)(6)(10)(19)(36)(17)(63)(30)(16)(46)(11)(14)(10)(22)(16)(58)(52)(3)(18)(37)(23)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'博客分类:
最近坛子里接连出现基于httpclient登录网站的帖子,也凑个热闹,分享一点基于htmlunit的登录经验谨以此文祭奠我刚刚逝去的鼠标----------------------------------------------分割线--------------------------------------------------- 目前最新版本2.7( Foxswily本人确认)基于httpclient封装(甚至已经做好启用httpclient4的准备),模拟浏览器操作,JavaScript支持较全面,包括主流的jQuery类库,这也是它的强大之处,一般网站的JS屏蔽可以轻松突破。举例说明
//创建浏览器,可以选择IE、FF等等
WebClient client = new WebClient(BrowserVersion.INTERNET_EXPLORER_7);
//获取某网站页面
HtmlPage page = client.getPage("");
//获取某页面元素,可通过id或name,(具体方式很多 --Foxswily)
HtmlElement elmt = page.getElementById("someid");
//HtmlElement elmt = page.getElementByName("somename");
//此例以文本框为例,先点击,再输入,完全跟真浏览器行为一致
elmt.click();
elmt.type("somewords");
//获取按钮
HtmlButton loginBtn = (HtmlButton)page.getElementById("btnId");
//点击并获得返回结果
Page resultPage = loginBtn.click();
//结果拿到了,想干啥您随意
log.debug(resultPage.getWebResponse().getContentAsString());
沿着这个思路展开一下,模拟登录不再需要破解什么js逻辑,用户实际做什么代码就模拟什么,轻松多了
额外的友情提示,Foxswily本人曾在登录用户量众多的discuz论坛时发现个小问题(已提交)造成登录后跳转失效,如有雷同参照解决吧问题描述
HtmlPage.executeRefreshIfNeeded()when html header has meta like "&META HTTP-EQUIV="Refresh" CONTENT="3 URL=http://www.some.org/some.html"&" it throws NumberFormatException.cause there is no ";" after "3" in the content.some forum sites have this bad writting html page.大意就是,自动跳转格式有问题,htmlunit解析不了,直接Exception了,改写HtmlPage的一个方法后通过。
private void executeRefreshIfNeeded() throws IOException {
// If this page is not in a frame then a refresh has already happened,
// most likely through the JavaScript onload handler, so we don't do a
// second refresh.
final WebWindow window = getEnclosingWindow();
if (window == null) {
final String refreshString = getRefreshStringOrNull();
if (refreshString == null || refreshString.length() == 0) {
int index = refreshString.indexOf(";");
final boolean timeOnly = (index == -1);
if (timeOnly && refreshString.indexOf(" ") == -1) {
// Format: &meta http-equiv='refresh' content='10'&
time = Double.parseDouble(refreshString);
} catch (final NumberFormatException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Malformed refresh string (no ';' but not a number): "
+ refreshString, e);
url = getWebResponse().getRequestSettings().getUrl();
if (refreshString.indexOf(";") == -1) {
index = refreshString.indexOf(" ");
// Format: &meta http-equiv='refresh'
// content='10;url='&
time = Double.parseDouble(refreshString.substring(0, index).trim());
} catch (final NumberFormatException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Malformed refresh string (no valid number before ';') "
+ refreshString, e);
index = refreshString.toLowerCase().indexOf("url=", index);
if (index == -1) {
if (LOG.isErrorEnabled()) {
LOG.error("Malformed refresh string (found ';' but no 'url='): "
+ refreshString);
final StringBuilder buffer = new StringBuilder(refreshString
.substring(index + 4));
if (buffer.toString().trim().length() == 0) {
// content='10; URL=' is treated as content='10'
url = getWebResponse().getRequestSettings().getUrl();
if (buffer.charAt(0) == '"' || buffer.charAt(0) == 0x27) {
buffer.deleteCharAt(0);
if (buffer.charAt(buffer.length() - 1) == '"'
|| buffer.charAt(buffer.length() - 1) == 0x27) {
buffer.deleteCharAt(buffer.length() - 1);
final String urlString = buffer.toString();
url = getFullyQualifiedUrl(urlString);
} catch (final MalformedURLException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Malformed URL in refresh string: " + refreshString, e);
final int timeRounded = (int)
getWebClient().getRefreshHandler().handleRefresh(this, url, timeRounded);
浏览 13822
论坛回复 /
(24 / 20090)
看懂了HtmlUnit自然知道这种提交和普通按钮没什么区别,仅仅在于你取的是Link还是Button
那个问题用htmlpage.executeJavaScript(script code)解决了,但最近遇到一个错误(用的是HtmlUnit 2.8):
警告: Expected content type of 'application/javascript' or 'application/ecmascript' for remotely loaded JavaScript element at '/commjs/ieupdate.js', but got 'application/x-javascript'.
似乎是个BUG,htmlunit作者承认的
Foxswily 写道验证码是所有类似工具都要面对的问题,我尝试两种方式解决
1.图像识别,这个可以单独拿来研究了,算法难度不小,外加现在的图片干扰越来越邪乎,不好实现。
2.显示图片人工解决,个人推荐这方式。毕竟登录一次可以程序保障长期在线,性价比高的方案:)
第二个解决方法,能不能帖段代码...
1,把登陆页面刷出来。
2,肉眼识别出验证码。
3,把验证码写死到程序里去。
是不是这样
验证码是所有类似工具都要面对的问题,我尝试两种方式解决
1.图像识别,这个可以单独拿来研究了,算法难度不小,外加现在的图片干扰越来越邪乎,不好实现。
2.显示图片人工解决,个人推荐这方式。毕竟登录一次可以程序保障长期在线,性价比高的方案:)
第二个解决方法,能不能帖段代码...
& 上一页 1
浏览: 56765 次
来自: 北京
huang_yong 写道XStream 对于 List&lt ...
XStream 对于 List&Map&Strin ...
我登录人人之类的都登录不上去,无法跳转请问一下是什么问题啊
jiangshuiy 写道JsonHierarchicalSt ...
JsonHierarchicalStreamDriver,可是 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
新建一个类:class InterceptWebConnection extends FalsifyingWebConnection{
public InterceptWebConnection(WebClient webClient) throws IllegalArgumentException{
super(webClient);
public WebResponse getResponse(WebRequest request) throws IOException {
WebResponse response=super.getResponse(request);
if(response.getWebRequest().getUrl().toString().endsWith("dom-drag.js")){
return createWebResponse(response.getWebRequest(), "", "application/javascript", 200, "Ok");
return super.getResponse(request);
}然后创建你自己的webClient:new InterceptWebConnection(webClient);
阅读(3676)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'让HtmlUnit忽略执行某个JavaScript文件',
blogAbstract:'开始是想在HtmlUnit执行完一些JS文件后获取对应URL的HTML页面,但是期间发生阻塞。。。怀疑是HtmlUnit在执行某个JS文件时陷入了无限循环中,检查是哪个JS文件造成的,如果该JS文件没有太大的价值就可以让HtmlUnit忽略它不执行它:新建一个类:',
blogTag:'htmluni,javascript,不执行',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:6,
publishTime:2,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}【图文】HtmlUnit_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
大小:1.79MB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢博客分类:
1·最近项目要求要把网站的首页静态化,网站的首页是和多个jsp页面组成,整体显示的时候大概5000多行,比较困难的地方是很多地方由于做了jquery特效,所以当初直接使用$.ajax获取的数据,并直接生成的html.其中又包括了一些处理逻辑,如
if(0 == li.length){
if(2==data.columncaption.length){//样式补位
li = $('&li class="wordspacing" id="'+data.columnid+'li"&&a href="#" class="pRound_tab"&'+data.columncaption+'&/a&&/li&');
li = $('&li id="'+data.columnid+'li"&&a href="#" &'+data.columncaption+'&/a&&/li&');
$('#BookrackUL').append(li);
var div=$('&div class="pane secondpane"&&a class="prev browse left"&&/a&&div class="scrollable w657" id="scrollable"&&div class="items" id="'+id+'fdiv" &&div id="'+id+'div'+k+'"&&p class="picBox mr35 ml15" id="'+id+'p"& &a href="&%=request.getContextPath()%&/ContentAction_getContent.action?id='+data.contentid+'" &&img src="'+data.contentsourceurl+'" width="100px" height="130px" alt="" /&&/a&&strong&'+data_caption+'&/strong&&a href="&%=request.getContextPath()%&/Page/knowmore.jsp?root='+data.columnid+'" class="more"&&img src="images/more.gif" alt="" /&&/a&&/p&&/div&&/div&&/div&&a class="next browse right"&&/a&&/div&');
$('#BookrackDiv').append(div);
if(0==j%5){//第一次创建一个div
var div=$('&div id="'+id+'div'+k+'"&&p class="picBox mr35 ml15"
id="'+id+'p"& &a href="&%=request.getContextPath()%&/ContentAction_getContent.action?id='+data.contentid+'" &&img src="'+data.contentsourceurl+'" width="100px" height="130px" alt="" /&&/a&&strong&'+data_caption+'&/strong&&a href="&%=request.getContextPath()%&/Page/knowmore.jsp?root='+data.columnid+'" class="more"&&img src="images/more.gif" alt="" /&&/a&&/p&&/div&');
$('#'+id+'fdiv').append(div);
}else if(4==j%5){//样式调整
var pp=$('&p class="picBox" id="'+id+'p"&&a href="&%=request.getContextPath()%&/ContentAction_getContent.action?id='+data.contentid+'" &&img src="'+data.contentsourceurl+'" width="100px" height="130px" alt="" /&&/a&&strong&'+data_caption+'&/strong&&a href="&%=request.getContextPath()%&/Page/knowmore.jsp?root='+data.columnid+'" class="more"&&img src="images/more.gif" alt="" /&&/a&&/p&');
$('#'+id+'div'+k+'').append(pp);
}else{//其他正常
var pp=$('&p class="picBox mr35" id="'+id+'p"&&a href="&%=request.getContextPath()%&/ContentAction_getContent.action?id='+data.contentid+'" &&img src="'+data.contentsourceurl+'" width="100px" height="130px" alt="" /&&/a&&strong&'+data_caption+'&/strong&&a href="&%=request.getContextPath()%&/Page/knowmore.jsp?root='+data.columnid+'" class="more"&&img src="images/more.gif" alt="" /&&/a&&/p&');
$('#'+id+'div'+k+'').append(pp);
原本是打算使用比较流行的freemaker来实现首页静态化,但以前没用过很难用freemaker标签实现这种效果.
2·静态化还有一种思路就要采用HttpClient获取首页生成的html文件保存作为静态页,但是很不幸的,HttpClient无法执行js,所有使用ajax获取的数据都无法获取到,于是这种方式也行不通
3·最后使用HtmlUnit.HtmlUnit的优势就是可以支持大部分js,对JQuery的支持也不错.大体思路就是先使用HtmlUnit获取执行完js的html,这个html生成的样式和html格式会出现一些问题.如果能满足需求则可以直接使用或者略加改动后使用.
如果这个html不能满足需求,那么就把它当做为静态数据来使用.这个时候我们先需要一个html模板文件,这个模板文件要保证首页的主题框架,然后从html按照各个div将数据填充进去.下面贴一些实现代码.
//创建一个可执行js,css,ajax的多功能WebClient
WebClient multiWebClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8);
multiWebClient.setJavaScriptEnabled(true);//执行JavaScript
multiWebClient.setCssEnabled(true);//执行css
multiWebClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置ajax代理
//创建一个普通的WebClient
WebClient commmonWebClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8);
commmonWebClient.setJavaScriptEnabled(false);
commmonWebClient.setCssEnabled(false);
//用多功能Client获取动态页面的html并执行完js后的页面
URL dynamicUrl = new URL("http://localhost:30010/WebSite");
HtmlPage dynamicPage = (HtmlPage) multiWebClient.getPage(dynamicUrl);
//根据项目需要,使用普通Client加载首页模板(避免执行模板里面的js,这些js都是真正要浏览器查看的时候才会执行)
URL constantUrl = new URL("http://localhost:30010/WebSite/wwwroot/indexTemple.html");
HtmlPage htmlpage = (HtmlPage) commmonWebClient.getPage(constantUrl);
HtmlElement body = htmlpage.getBody();
* 未详细测试的结论:getElementById一个元素只能取一次,取了之后再取就是空元素,其子也无法用getElementById取到
* 开始处理header
appendChildren(body.getElementById("_static_nav"), dynamicPage.getElementById("_static_nav"));
//开始处理_static_leftbox
//处理图片滚动KSS_content
appendChildren(body.getElementById("KinSlideshow"), dynamicPage.getElementById("KSS_content"));
//处理最新电子书
appendChildren(body.getElementById("e_bookDiv"), dynamicPage.getElementById("e_bookDiv"));
//取出content
HtmlElement content = body.getElementById("content");
//开始处理_static_rightbox
content.appendChild(dynamicPage.getElementById("_static_rightbox"));
//添加div换行
DomElement clearDiv = htmlpage.createElement("div");
clearDiv.setAttribute("class", "clear");
//一个DomElement貌似只能使用一次
content.appendChild(clearDiv.cloneNode(true));
//开始处理_static_bookshow
content.appendChild(dynamicPage.getElementById("_static_bookshow"));
content.appendChild(clearDiv.cloneNode(true));
//开始处理_static_assistBox,secrecyRelevancediv,_static_optionBox
content.appendChild(dynamicPage.getElementById("_static_assistBox"));
content.appendChild(dynamicPage.getElementById("secrecyRelevancediv"));
content.appendChild(dynamicPage.getElementById("_static_optionBox"));
content.appendChild(clearDiv.cloneNode(true));
//开始处理_static_bookShowA
content.appendChild(dynamicPage.getElementById("_static_bookShowA"));
content.appendChild(clearDiv.cloneNode(true));
//开始处理_static_serve
content.appendChild(dynamicPage.getElementById("_static_serve"));
//开始处理footer
body.appendChild(clearDiv.cloneNode(true));
body.appendChild(dynamicPage.getElementById("_static_footer"));
//处理错误
String finalHtml =htmlpage.asXml().replace("&?xml version=\"1.0\" encoding=\"utf-8\"?&", "&!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"&");
finalHtml = finalHtml.replaceAll("&a class=\"prev browse left\"/&", "&a class=\"prev browse left\" &&/a&");
finalHtml = finalHtml.replaceAll("&a class=\"next browse right\"/&", "&a class=\"next browse right\" &&/a&");
finalHtml = finalHtml.replaceAll("&b/&", "&b&&/b&");
finalHtml = finalHtml.replaceAll("scrollable_2", "scrollable");
stringToFile(finalHtml,"E:\\WayOfGlory\\WebSite\\WebContent\\wwwroot\\indexHome.html");
上面一段代码虽然不长,但实际上是个非常漫长的处理过程,从静态数据html中获取到的&div&&/div&经常会无法直接使用,这时就需要不断的和浏览器(比如chrome)生成的真正静态页进行比对.虽然过程很漫长,但总比无法实现要强.
下面贴上刚刚使用了的两个小方法.
public DomElement appendChildren(DomElement target,DomElement source){
Iterator it = source.getChildElements().iterator();
while(it.hasNext()){
DomElement ele = (DomElement) it.next();
target.appendChild(ele);
public void stringToFile(String content,String path){
FileWriterWithEncoding fileWriter = new FileWriterWithEncoding(path,"utf-8");
fileWriter.write(content);
fileWriter.flush();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
这种实现是自己瞎研究的,如果有哪位大虾有更好的方法,欢迎指点.
浏览: 6512 次
保留ajax没什么问题吧。既然是异步请求就有异步请求的理由
其实保留部分ajax的东西未必就不好
静态化不需要处理js吧,除非界面做的有点。。。
而且ajax ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 javascript注册页面 的文章

 

随机推荐