Reactor 3.x(Java):用于web抓取
这里没有反应堆 这更像是一个如何解决的问题 比方说,我有一个网站,我想刮包含一个页面集的搜索结果。搜索结果页的数量未知。每个搜索页都有一个指向下一页的链接。我想从所有页面中刮取所有搜索结果并处理每个搜索结果 我如何使用Reactor(Mono/Flux)在Java中实现这一点 我想尽可能地“反应性地”做这件事 基本上,以下命令伪代码的Reactor(3.x)版本:Reactor 3.x(Java):用于web抓取,java,project-reactor,Java,Project Reactor,这里没有反应堆 这更像是一个如何解决的问题 比方说,我有一个网站,我想刮包含一个页面集的搜索结果。搜索结果页的数量未知。每个搜索页都有一个指向下一页的链接。我想从所有页面中刮取所有搜索结果并处理每个搜索结果 我如何使用Reactor(Mono/Flux)在Java中实现这一点 我想尽可能地“反应性地”做这件事 基本上,以下命令伪代码的Reactor(3.x)版本: String url = "http://example.com/search/1"; Optional<Do
String url = "http://example.com/search/1";
Optional<Document> docOp = getNextPage(url); (1)
while (docOp.isPresent()) {
Document doc = docOp.get();
processDoc(doc); (2)
docOp = getNextPage(getNextUrl(doc)); (3)
}
// (1) Get the first page of search results
// (2) Process all the search results on this page asynchronously
// (3) Find the next page URL, and get that page
stringurl=”http://example.com/search/1";
可选docOp=getNextPage(url);(1)
while(docOp.isPresent()){
Document doc=docOp.get();
processDoc(doc);(2)
docOp=getNextPage(getnextur(doc));(3)
}
//(1)获取搜索结果的第一页
//(2)异步处理此页面上的所有搜索结果
//(3)找到下一页URL,并获取该页
在我的帮助下,我找到了这个解决方案。这可能并不理想。我很想得到任何人可能看到的问题的反馈
public void scrape() {
Try<Document> firstDocTry = this.getSearchResultsPage(Option.<Document>none().toTry()); (1)
// Generate a flux where each element in the flux is created using the current element
Flux.<Try<Document>, Try<Document>>generate(() -> firstDocTry, (docTry, sink) -> { (2)
docTry = this.getSearchResultsPage(docTry);
docTry.isFailure() ? sink.complete() : sink.next(docTry);
return docTry;
})
.flatMap(docTry -> this.transformToScrapedLoads(docTry)) (3)
.log()
.subscribe(scrapedLoad ->
scrapedLoadRepo.save(scrapedLoad) (4)
);
}
protected Try<Document> getSearchResultsPage(Try<Document> docTry) {
...
}
protected Flux<ScrapedLoad> transformToScrapedLoads(Try<Document> docTry) {
...
}
public void scrape(){
尝试firstDocTry=this.getSearchResultsPage(Option.none().toTry());(1)
//生成通量,其中通量中的每个元素都是使用当前元素创建的
生成(()->firstDocTry,(docTry,sink)->{(2)
docTry=this.getSearchResultsPage(docTry);
docTry.isFailure()?sink.complete():sink.next(docTry);
返回博士学位;
})
.flatMap(docTry->this.transformToScrapedLoads(docTry))(3)
.log()
.订阅(scrapedLoad->
scrapedLoadRepo.save(scrapedLoad)(4)
);
}
受保护的Try getSearchResultsPage(Try docTry){
...
}
受保护的通量转换到压缩负载(请尝试docTry){
...
}
(1) 在这里使用Javaslang的单子Try和OptionfirstDocTry的种子是发电机的种子。getSearchResultsPage()知道
如果没有提供文档,则从搜索的第一页开始
(2) 在这里使用发电机。通量中发布的每个元素由先前的元素确定
(3) transform方法将每个文档转换为一个流量,将其组合并作为单个流量发送给订阅
(4) 用户对通量产生的每个元素进行操作。在这种情况下,坚持他们