2017-02-02 63 views
0

Reactor noob here。Reactor 3.x(Java):用于网页抓取

这是更多的HowTo问题。

比方说,我有一个网站,我想抓取包含一组分页的搜索结果。搜索结果页面的数量未知。每个搜索页面都有一个指向下一页的链接。我想抓取所有页面的所有搜索结果并处理每个搜索结果。

我该如何使用Reactor(单声道/通量)在Java中完成此操作?

我想尽可能做到“反应性”。

基本上,电抗器(3.X)以下版本势在必行伪代码:

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 

回答

0

https://gitter.im/reactor/reactor一些帮助我来到这个解决方案。它可能不理想。我很想得到任何人可能看到的问题的反馈。

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) { 
    ... 
} 

(1)使用Javaslang的单子尝试和选择这里。 'firstDocTry'播种发生器。 getSearchResultsPage()知道到 开始于搜索的第一页,如果没有Document提供。

(2)在这里使用发生器。发表在焊剂中的每个元素是由现有元件

(3)的变换方法将每个文档的助焊剂,其被组合并且发送到订阅作为单个通量

(4)用户操作确定在由Flux生成的每个元素上。在这种情况下,坚持他们。