2017-02-02 10 views
0

Реактор noob здесь.Reactor 3.x (Java): для веб-соскабливания

Это более чем вопрос.

Предположим, у меня есть веб-сайт, который я хочу очистить, содержащий постраничный набор результатов поиска. Количество страниц результатов поиска неизвестно. На каждой странице поиска есть ссылка на следующую страницу. Я хочу очистить все результаты поиска от всех страниц и обработать каждый результат поиска.

Как я могу использовать Reactor (Mono/Flux), чтобы выполнить это на Java?

Я хочу сделать это как можно «реактивно».

В основном, версия Reactor (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() знает, что начинается с первой страницы поиска, если документ не предоставлен.

(2) Использование генератора здесь. Каждый элемент опубликован в Flux определяется предыдущим элементом

(3) преобразование метод преобразует каждый документ в качестве флюса, которые объединяются и передаются на подписку как единый Flux

(4) Абонент работает на каждый элемент, созданный Flux. В этом случае они сохраняются.