java gui 颜色从html_关于swing:用于显示网页和返回HTML的Java GUI

我需要一个如下工作流程:

// load xyz.com in the browser window

// the browser is live, meaning users can interact with it

browser.load("http://www.google.com");

// return the HTML of the initially loaded page

String page = browser.getHTML();

// after some time

// user might have navigated to a new page, get HTML again

String newpage = browser.getHTML();

我很惊讶地看到Java GUI如JavaFX(http://lexandera.com/2009/01/extracting-html-from-a-webview/)和Swing有多难。

有一些简单的方法可以在Java中获得此功能吗?

您是否看过嵌入JavaFX运行时的WebKit?

是的,很难从JavaFX中获取HTML(lexandera.com/2009/01/extracting-html-from-a-webview)。

@moeb你提供的链接是针对Android WebView的,而不是像zenbeni建议的JavaFX。

我不知道这是否有用,但您可以查看此链接:stackoverflow.com/questions/14273450/

这是一个使用JavaFX的人为例子,它将html内容打印到System.out--它不应该太复杂,无法适应创建getHtml()方法。 (我已经使用JavaFX 8对其进行了测试,但它也适用于JavaFX 2)。

每次加载新页面时,代码都会打印HTML内容。

注意:我从这个答案中借用了printDocument代码。

public class TestFX extends Application {

@Override

public void start(Stage stage) throws Exception {

try {

final WebView webView = new WebView();

final WebEngine webEngine = webView.getEngine();

Scene scene = new Scene(webView);

stage.setScene(scene);

stage.setWidth(1200);

stage.setHeight(600);

stage.show();

webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener() {

@Override

public void changed(ObservableValue extends State> ov, State t, State t1) {

if (t1 == Worker.State.SUCCEEDED) {

try {

printDocument(webEngine.getDocument(), System.out);

} catch (Exception e) { e.printStackTrace(); }

}

}

});

webView.getEngine().load("http://www.google.com");

} catch (Exception e) {

e.printStackTrace();

}

}

public static void printDocument(Document doc, OutputStream out) throws IOException, TransformerException {

TransformerFactory tf = TransformerFactory.newInstance();

Transformer transformer = tf.newTransformer();

transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"no");

transformer.setOutputProperty(OutputKeys.METHOD,"xml");

transformer.setOutputProperty(OutputKeys.INDENT,"yes");

transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");

transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4");

transformer.transform(new DOMSource(doc), new StreamResult(new OutputStreamWriter(out,"UTF-8")));

}

public static void main(String[] args) {

launch(args);

}

}

谢谢。一个问题 - changed()内部代码的执行模型究竟是什么?它是否在与调用load()的线程的单独线程中执行?

上面的代码中没有任何内容在JavaFX Thread上执行。但请注意,load不会加载页面,它只要求WebEngine安排页面加载任务 - 然后WebEngine使用后台线程实际加载页面以避免阻止UI。加载完成后,WebEngine将调用JavaFX Thread上的changed方法。有关线程模型的更多详细信息,请参阅javadoc。

谢谢。我想在加载和打印之间进行排序。像下面这样的东西 - load a page, wait till print is complete, load another page, wait till print is complete,。我怎样才能做到这一点?

@Moeb你可以在changed方法中加载下一页:printDocument(...); webView.getEngine().load(getNextPageUrl()); - getNextPageUrl是一个简单的方法,它返回一个数组的项目,并在每次调用时递增索引。像:private String[] pages = ...; private index i; private String getNextPage() { return pages[++i]; }。现在没有时间写一个完整的例子,抱歉。

这是一个非常好的提示,谢谢!

下面是一个SimpleBrowser组件,它是一个Pane,包含WebView。

gist的源代码。

样品用法:

SimpleBrowser browser = new SimpleBrowser()

.useFirebug(true);

// ^ useFirebug(true) option - will enable Firebug Lite which can be helpful for

// | debugging - i.e. to inspect a DOM tree or to view console messages

Scene scene = new Scene(browser);

browser.load("http://stackoverflow.com", new Runnable() {

@Override

public void run() {

System.out.println(browser.getHTML());

}

});

browser.getHTML()放在Runnable中,因为需要等待网页下载和渲染。尝试在页面加载之前调用此方法将返回一个空页面,因此将其包装到runnable中是一种简单的方法,我想出来等待页面加载。

import javafx.beans.value.ChangeListener;

import javafx.beans.value.ObservableValue;

import javafx.concurrent.Worker;

import javafx.scene.layout.*;

import javafx.scene.web.WebEngine;

import javafx.scene.web.WebView;

public class SimpleBrowser extends Pane {

protected final WebView webView = new WebView();

protected final WebEngine webEngine = webView.getEngine();

protected boolean useFirebug;

public WebView getWebView() {

return webView;

}

public WebEngine getEngine() {

return webView.getEngine();

}

public SimpleBrowser load(String location) {

return load(location, null);

}

public SimpleBrowser load(String location, final Runnable onLoad) {

webEngine.load(location);

webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener() {

@Override

public void changed(ObservableValue extends Worker.State> ov, Worker.State t, Worker.State t1) {

if (t1 == Worker.State.SUCCEEDED) {

if(useFirebug){

webEngine.executeScript("if (!document.getElementById('FirebugLite')){E = document['createElement' + 'NS'] && document.documentElement.namespaceURI;E = E ? document['createElement' + 'NS'](E, 'script') : document['createElement']('script');E['setAttribute']('id', 'FirebugLite');E['setAttribute']('src', 'https://getfirebug.com/' + 'firebug-lite.js' + '#startOpened');E['setAttribute']('FirebugLite', '4');(document['getElementsByTagName']('head')[0] || document['getElementsByTagName']('body')[0]).appendChild(E);E = new Image;E['setAttribute']('src', 'https://getfirebug.com/' + '#startOpened');}");

}

if(onLoad != null){

onLoad.run();

}

}

}

});

return this;

}

public String getHTML() {

return (String)webEngine.executeScript("document.getElementsByTagName('html')[0].innerHTML");

}

public SimpleBrowser useFirebug(boolean useFirebug) {

this.useFirebug = useFirebug;

return this;

}

public SimpleBrowser() {

this(false);

}

public SimpleBrowser(boolean useFirebug) {

this.useFirebug = useFirebug;

getChildren().add(webView);

webView.prefWidthProperty().bind(widthProperty());

webView.prefHeightProperty().bind(heightProperty());

}

}

演示浏览器:

import javafx.application.Application;

import javafx.event.ActionEvent;

import javafx.event.EventHandler;

import javafx.scene.Scene;

import javafx.scene.control.Button;

import javafx.scene.control.TextField;

import javafx.scene.layout.HBox;

import javafx.scene.layout.Priority;

import javafx.scene.layout.VBox;

import javafx.scene.layout.VBoxBuilder;

import javafx.stage.Stage;

public class FXBrowser {

public static class TestOnClick extends Application {

@Override

public void start(Stage stage) throws Exception {

try {

SimpleBrowser browser = new SimpleBrowser()

.useFirebug(true);

final TextField location = new TextField("http://stackoverflow.com");

Button go = new Button("Go");

go.setOnAction(new EventHandler() {

@Override

public void handle(ActionEvent arg0) {

browser.load(location.getText(), new Runnable() {

@Override

public void run() {

System.out.println("---------------");

System.out.println(browser.getHTML());

}

});

}

});

HBox toolbar  = new HBox();

toolbar.getChildren().addAll(location, go);

toolbar.setFillHeight(true);

VBox vBox = VBoxBuilder.create().children(toolbar, browser)

.fillWidth(true)

.build();

Scene scene = new Scene( vBox);

stage.setScene(scene);

stage.setWidth(1024);

stage.setHeight(768);

stage.show();

VBox.setVgrow(browser, Priority.ALWAYS);

browser.load("http://stackoverflow.com");

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

launch(args);

}

}

}

根据我不了解你的项目的东西,无论是天才还是愚蠢,但你可以使用真正的浏览器并使用Selenium Webdriver进行测量。只是从另一个答案中可以看出这一点,你走的是一条艰难的道路。

还有一个关于用webdriver提取html的问题。这是关于使用python,但webdriver也有一个java api。

你可能想看到djproject。但可能你会发现JavaFX的使用更容易。

没有一个简单的解决方案。事实上,构建自己的浏览器可能根本就没有解决方案。

关键问题是互动。如果您只想显示内容,那么JEditorPane和许多第三方库使这个目标更容易实现。如果您确实需要用户与网页进行交互,则可以:

让用户使用普通浏览器进行交互

构建一个GUI,调用Web服务/ URL进行交互,但显示由您决定。

在返回HTML方面,听起来您正在尝试捕获历史记录或刷新页面。在任何一种情况下,听起来你都是错误的技术。修改原始站点,或在浏览器中使用Greasemonkey或类似的东西添加一些java脚本。

当然它是可行的,Selenium做到了。不仅如此,Selenium可以在您(或它)与页面交互时捕获呈现页面的屏幕截图。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值