我目前正在学习HtmlUnit以便抓取网站。一切顺利,直到我遇到一个动态页面(例如,我正在使用Pinterest网站),当用户向下滚动时,动态添加了哪些元素。
我尝试过几种方法可以在真实的浏览器中触发滚动(我将在下面显示)。 在进一步讨论之前,我想提一下我已经设置了以下配置:
webclient.setJavaScriptEnabled(true);
webclient.setAjaxController(new NicelyResynchronizingAjaxController());
允许'说我想让所有关注者都在Pinterest上。我导航到那个页面,现在从第一次只有24个,我想向下滚动,触发Ajax调用服务器并检索下一组关注者的事件。
1)用于触发窗口滚动的简单javascript或jQuery代码。
ScriptResult sr = followersPage.executeJavaScript("window.scrollBy(0,1000)");
// One version in jQuery
// ScriptResult sr = followersPage.executeJavaScript("$(window).scrollTop(0,1000);");
// also tried with the body, html, with animation
// ScriptResult sr = followersPage.executeJavaScript("$("html, body").animate({ scrollTop: $(document).height() }, 1000);");
webclient.waitForBackgroundJavaScript(10000);
followersPage = (HtmlPage)sr.getNewPage();
=>当我检查到顶部的距离时,它等于0,结果页面与原始页面相同。在Eclipse中进行调试时,当我跨越执行javascript的行时,它会直接转到下一行,没有任何延迟。如果我写任何其他javascript,例如:
ScriptResult sr = followersPage.executeJavaScript("$(div.GridItems).html('new content')");
你可以注意到调试器在该行上挂了半秒,这意味着javascript被执行了。
2)将焦点从一个跟随者锚点更改为另一个(我选择了锚点,因为当您单击TAB键时它在焦点顺序中使用):
HtmlDivision gridItems = followersPage.getFirstByXPath("//div[contains(concat(' ',@class,' '),' GridItems ')]");
List<HtmlDivision> els = (List<HtmlDivision>) gridItems.getByXPath("//div[@class='item ']");
List<HtmlDivision> items = (List<HtmlDivision>) gridItems.getByXPath("//div[@class='item ']");
for (HtmlDivision item : items) {
HtmlAnchor a = item.getFirstByXPath("//a[@class='userWrapper']");
a.focus();
webClient.waitForBackgroundJavaScript(1000);
}
followersPage = (HtmlPage) webClient.getCurrentWindow().getEnclosedPage();
同样,没有发生滚动。结果页面与原始页面保持一致
3)创建一个触发窗口滚动事件的按钮:
HtmlButton scrollButton = (HtmlButton) followersPage.createElement("button");
scrollButton.setAttribute("type", "button");
scrollButton.setAttribute("onclick", "window.scrollTo(0,document.body.scrollHeight);");
gridItems.appendChild(scrollButton);
followersPage = scrollButton.click();
不幸的是,它没有用。
我尝试了许多其他方法但直到现在都没有积极的结果。
我阅读了很多相关文章,也就是关于该主题的stackoverflow。似乎没有人设法使用HtmlUnit进行滚动工作,因为大多数问题仍未得到答复。这就是为什么我想知道这个功能是否有用。
有人设法滚动页面(简单页面,没有ajax)吗? 有人设法滚动页面,触发某个ajax调用的事件吗?
答案 0 :(得分:0)
在这种情况下,我建议您使用casperjs而不是htmlunit,我尝试过 使用htmlunit打开pinterest并获得
runtimeError: message=[Property 0 not found.] sourceName=[https://s.pinimg.com/webapp/js/vendor-react-d20f99c48b5d58e4821c.js] line=[1] lineSource=[null] lineOffset=[0]
因此它看起来 htmlunit 确实没有对js的良好支持,即使最新版本为2.31 ..
这是使用 casperjs 的演示代码:
var utils = require('utils')
var fs = require('fs')
var system = require('system')
var casper = require('casper').create({
verbose: true,
logLevel: 'debug',
localToRemoteUrlAccessEnabled: true,
webSecurityEnabled: false,
plainTextAllContent: false,
viewportSize: {
width: 1440,
height: 800
},
onError: function(casper, msg, backtrace) {
utils.dump(backtrace)
}
});
var cookie = fs.read('cookie.txt').trim()
casper.on('started', function() {
this.page.onError = function(msg, trace) {
casper.echo('Error => ' + msg + '\nError trace => ')
utils.dump(trace)
}
this.page.customHeaders = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,en;q=0.5",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
"Pragma": "no-cache",
"Cookie": cookie
}
});
casper.start('https://www.pinterest.com', function() {
this.then(function() {
this.waitForSelector('div[class="_wx _2h"]', function() {
this.echo("waitForSelector 'div[class=_wx _2h]' is done")
this.scrollTo(0, 1000);
this.wait(5000, function() {
this.scrollTo(0, 2000);
})
})
})
});
将上述代码保存到名为demo.js的文件中,然后使用以下命令启动casperjs
casperjs --engine=slimerjs demo.js
然后,您将在视觉上看到Firefox浏览器启动并开始工作!