获取JavaFXWebEngine解释文档

获取JavaFXWebEngine解释文档,javafx,domdocument,javafx-webengine,Javafx,Domdocument,Javafx Webengine,对WebEngine对象调用getDocument()方法只返回从服务器检索到的源代码,而不执行JavaScript(仍然有元素)。如果在Chrome中使用“查看源代码”,您将看到这种源代码。如何检索已运行JavaScript的已解释源代码 public Browser() { WebView browser = new WebView(); final WebEngine webEngine = browser.getEngine(); webEngine.load("

对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);
            }
        }
    });
}
公共浏览器(){
WebView浏览器=新建WebView();
final-WebEngine-WebEngine=browser.getEngine();
webEngine.load(“*************************************”);
webEngine.getLoadWorker().stateProperty().addListener(新的ChangeListener()){
@凌驾

public void changed(observevasive value我不确定你的问题是否正确,但如果你正在寻找一种方法来打印你正在加载的web的可见内容,从
文档
获取
DocumentElement
将允许你深入了解它的结构并过滤你需要的内容

此方法将打印所需标签的内容:

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++);
        }
    }
}
这将打印所有具有缩进级别的DOM标记,对于指定的标记,它还将打印内容。在这种情况下,使用标记“A”,它将打印所有链接的内容


我不确定这是否会有帮助。请澄清您的问题,否则。

这对我来说是正常的。在本例中,
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);
    }
}
导入javafx.application.application;
导入javafx.concurrent.Worker;
导入javafx.scene.scene;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.web.WebView;
导入javafx.stage.stage;
导入org.w3c.dom.Document;
导入org.w3c.dom.Node;
导入org.w3c.dom.NodeList;
公共类WebViewOnLoadExample扩展了应用程序{
@凌驾
公共无效开始(阶段primaryStage){
WebView WebView=新建WebView();
webView.getEngine()
.getLoadWorker()
.stateProperty()
.addListener((obs、旧状态、新状态)->{
if(newState==Worker.State.successed){
Document doc=webView.getEngine().getDocument();
showNodeContent(文档,0);
}
});
BorderPane根=新的BorderPane(webView);
原始阶段。设置场景(新场景(根,600400));
primaryStage.show();
webView.getEngine().loadContent(“”)
+""
+“函数setText(){”
+“document.getElementById(\“target\”).appendChild(document.createTextNode(\“Hello World\”);”
+"}"
+""
+""
+"");
}
私有void showNodeContent(节点n,int深度){

对于(int i=0;i您面临的问题如下:
LoadWorker
的状态在JavaScript运行完成之前设置为
successed
。JavaScript实际上运行(如@James_D的回复所示)但是当它完成时没有回调来发出信号。好吧,没有可靠的方法来检测WebEngine何时执行完JS

作为一种解决方法,您可以在状态更改为Successed后播放一个
PauseTransition
,它可以被滥用,在JavaFX线程上充当
sleep
(JS在后台线程中执行,该线程也加载文档,所以JS不会暂停)。但是,睡眠(等待JS完成)它本质上违反了JavaFX的核心原则决不阻塞UI线程。除此之外,等待一段时间并不保证JS在这段时间过去之前执行完毕

我也遇到过同样的问题,但我还没有找到一个像样的解决方案。如果有,请告诉我!

正如沃克斯特所指出的:
在JavaScript完成运行之前,LoadWorker的状态设置为Successed。

您可以做的是:
从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>
。。。
//这里的自动执行函数
(功能(){
app.exit();
})();

请参见此处:

不,这不是问题所在。我在打印文档时没有遇到任何问题。问题在于文档的内容是错误的;它仍然包含元素,而不是运行JavaScript。请注意,脚本将始终与页面一起加载,如果访问DOM,您将找到这些脚本。您是指第o部分吗如果javascript仍在加载或挂起,而加载状态为“成功”
?了解这些脚本将允许您执行它们,如果是这样的话…您可以指定您试图访问DOM的内容吗?在您要加载的网页中,可能有一些脚本不需要在加载时执行,但会延迟触发您可以从JavaFX调用它们中的任何一个,甚至可以插入您自己的脚本以添加更多功能。另外,请注意,在执行这些脚本后,DOM正在发生变化,因此您需要再次检查其内容。由于您没有提供有关您的问题的更多详细信息,因此很难说…有趣…它在r me。我将看看是否可以修改我的原始代码,并找出它们的分歧。实际上,似乎正在执行JavaScript。但是,在网页的图形版本中,有一些字符串我在DOM中找不到。你知道为什么会出现这种情况吗?有关更好的解决方案,请参阅此处从JavaScript调用Java:d将自动执行的Javascript代码添加到HTML页面的末尾。
...

<script>
// self executing function here
(function() {
   app.exit();
})();
</script>

</body>
</html>