我正在使用Selenium和ChromeDriver用Java编写一个抓取工具,我想将其包装到Observable中(以便于异步(。这是从我的解析器类返回 Observable 的代码:
return Observable.interval(5000, 5000, TimeUnit.MILLISECONDS)
.doOnSubscribe(ignored -> initialize())
.doOnNext(ignored -> refreshPage())
.map(ignored -> getHtml())
.map(this::parse)
.flatMap(Observable::fromIterable)
.doFinally(() -> finish())
.share();
所以在这里,initialize()
基本上创建了一个Selenium WebDriver的配置实例,refreshPage()
重新加载页面并等待它加载,getHtml()
只是driver.getPageSource()
finish()
driver.quit()
其中driver
是Selenium WebDriver的实例。我遇到的问题是当我订阅这个可观察的并在以后处理它时。我从refreshPage()
中得到一个例外,说我在driver.quit()
之后driver
调用了一个方法(或者在上面的代码中,这意味着refreshPage()
是在finish()
之后调用的(。
我应该如何创建/修改我的源可观察,以便在处置时正确释放我的资源?(我希望finish()
始终在可观察链中的其他所有内容完成后调用(。
更新: 我的finish()
函数是:
public void finish() {
driver.quit();
}
doFinally
按照你的怀疑去做。 它在以下之后执行关联的Action
:
onError
,onComplete
或- 关联的下游取消/处置流
但是,我怀疑可能发生的情况是,您可能在finish()
的主体中调用driver.quit()
,而不是在它返回的Action
中调用。 假设driver
在refreshPage()
中使用,该错误是有意义的,因为doFinally()
本身的实际调用(而不是它返回Action
(是尽早完成的,以构建流行为,refreshPage()
是此后流中使用driver
的最早点。
如果您的代码如下所示:
private Action finish() {
driver.quit();
return () -> {
...
};
}
。然后将调用移动到quit()
移动到Action
体内,例如:
private Action finish() {
return () -> {
driver.quit();
};
}
如果我的假设是错误的,你能用finish()
的代码更新问题吗? 我很想知道那里发生了什么。