对我来说,在WebEngine对象上调用getDocument()方法只返回从服务器检索到的源,而不执行JavaScript(仍有元素)。如果您使用"查看来源"这是您会看到的那种来源。在Chrome中。如何在已运行JavaScript的情况下检索已解释的源?
public Browser() {
WebView browser = new WebView();
final WebEngine webEngine = browser.getEngine();
webEngine.load("*******************************");
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
@Override
public void changed(ObservableValue<? extends State> ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
Document doc = webEngine.getDocument();
printDocument(doc);
}
}
});
}
答案 0 :(得分:1)
这对我来说是预期的。在此示例中,div
包含一个文本节点,其文本由Javascript函数设置:
import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class WebViewOnLoadExample extends Application {
@Override
public void start(Stage primaryStage) {
WebView webView = new WebView();
webView.getEngine()
.getLoadWorker()
.stateProperty()
.addListener((obs, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
Document doc = webView.getEngine().getDocument();
showNodeContent(doc, 0);
}
});
BorderPane root = new BorderPane(webView);
primaryStage.setScene(new Scene(root, 600, 400));
primaryStage.show();
webView.getEngine().loadContent("<html>"
+"<head><script>"
+"function setText() {"
+" document.getElementById(\"target\").appendChild(document.createTextNode(\"Hello World\"));"
+"}"
+"</script></head>"
+"<body onload='setText()'>"
+"<div id='target'></div></body></html>");
}
private void showNodeContent(Node n, int depth) {
for (int i=0; i<depth; i++) {
System.out.print(" ");
}
System.out.println(n.getNodeName()+":"+n.getNodeValue());
NodeList children = n.getChildNodes() ;
for (int i=0; i<children.getLength(); i++) {
showNodeContent(children.item(i), depth+1);
}
}
public static void main(String[] args) {
launch(args);
}
}
答案 1 :(得分:1)
您遇到的问题如下:在JavaScript运行完成之前,LoadWorker
的状态设置为SUCCEEDED
。 JavaScript 确实实际上正在运行(如@ James_D&#39;回复中所示),但完成后没有回调信号。 AFAIK,没有可靠的方法来检测WebEngine何时执行JS。
你可以做的解决方法是在状态更改为SUCCEEDED之后播放PauseTransition
,这可能会被滥用来像JavaFX线程上的sleep
一样(JS在后台线程中执行)也会加载Document,所以JS不会暂停)。但是,休眠(等待JS完成)本质上违反了JavaFX的核心原则从不来阻止UI线程。最重要的是,等待一段时间并不能保证JS在该时间段过去之前完成执行。
我遇到了同样的问题而我找不到合适的解决方案。如果你这样做,请告诉我!
答案 2 :(得分:0)
我不确定我的问题是否正确,但如果您正在寻找方法,请打印正在加载的网络的可见内容,从DocumentElement
获取Document
{1}}允许您深入了解其结构并过滤所需内容。
此方法将打印所需标签的内容:
private void printElement(Element el, int level){
NodeList childNodes = el.getChildNodes();
for(int j=0; j<level; j++) System.out.print("-");
System.out.print("tag: "+el.getNodeName());
if(el.getNodeName().equals("A")){
System.out.print(", content: "+el.getTextContent());
}
System.out.println("");
for(int i=0; i<childNodes.getLength(); i++){
Node item = childNodes.item(i);
if(item instanceof Element){
printElement((Element)item, level++);
}
}
}
所以,一旦您加载了网址,只需将其命名为:
if(newState==State.SUCCEEDED){
Document doc = webEngine.getDocument();
Element el = doc.getDocumentElement();
printElement(el,0);
}
这将打印所有带有缩进级别的DOM标记,对于指定的标记,它也会打印内容。在这种情况下,使用标签&#34; A&#34;它会打印所有链接的内容。
我不确定这是否有帮助。请另外澄清您的问题。
答案 3 :(得分:0)
正如Warkst指出:
在JavaScript运行完成之前,LoadWorker的状态设置为SUCCEEDED。
你能做的是:
从JavaScript回调Java
public class JavaApplication {
public void exit() {
Platform.exit();
}
}
...
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("app", new JavaApplication());
然后,您可以从HTML页面引用对象和方法:
<a href="" onclick="app.exit()">Click here to exit application</a>
或放在HTML的末尾:
...
<script>
// self executing function here
(function() {
app.exit();
})();
</script>
</body>
</html>
见这里:http://docs.oracle.com/javafx/2/api/javafx/scene/web/WebEngine.html