2

NOMADS Web サイトのすべてのモデルを含めるために、 rNOMADS パッケージの更新を作成しています。これを行うには、モデルごとに html ディレクトリ ツリーを検索する必要があります。この木の深さや枝の数は事前にはわかりません。そのため、トップページのリンクを再帰的に検索し、各リンクをたどり、リンクがなくなったページの URL を返す単純な Web クローラーを作成しています。そんなページがモデルデータのダウンロードページです。 検索する必要がある URLの例を次に示します。

このページの下にあるすべての Web ページのアドレスを取得したいと考えています。私はこのコードを試みました:

library(XML)
url <- "http://nomads.ncep.noaa.gov/cgi-bin/filter_cmcens.pl"

WebCrawler <- function(url) {
    doc <- htmlParse(url)
    links <- xpathSApply(doc, "//a/@href")
    free(doc)
    if(is.null(links)) { #If there are no links, this is the page we want, return it!
        return(url)
    } else {
       for(link in links) { #Call recursively on each link found
           print(link)
           return(WebCrawler(link))
        }
    }
}

ただし、すべての「行き止まり」のページのリストを返す良い方法がわかりません。代わりに、このコードはモデル ページのリスト全体ではなく、1 つのモデル ページのみを返します。グローバル変数を宣言し、その変数に URL を保存することもできますが、これを行うためのより良い方法があるかどうか疑問に思っています。この関数を構築して、すべてのページのリストを取得するにはどうすればよいですか?

4

1 に答える 1

1

あなたのエラーは再帰にあります:

## THIS IS INCORRECT
for(link in links) { #Call recursively on each link found
           print(link)
           return(WebCrawler(link))   <~~~ Specifically this line
        }

ここには再帰的なプロパティはありません。単一のブランチに沿って深く掘り下げているだけです。

      *
    /   \
    \
     \
      \ 
       \
        * 

の値を返したくありませんWebCrawler(link)
むしろ、その値をキャプチャしてから、値のコレクションを返します。

ret <- vector("list", length=length(links))
for(link in links) { #Call recursively on each link found
           print(link)
           ret[[link]] <-  WebCrawler(link)   <~~~ Specifically this line
        }
return(ret) # or  return(unlist(ret))

アップデート:

最終出力として何を期待するかを検討する価値があるでしょうか? 深くネストされたリストが得られます。エンドノードだけがunlist(.. recursive=TRUE, use.names=FALSE)必要な場合は、リストから除外することもできますが、それにより速度がさらに低下する可能性があります。確かにベンチマークする価値があるかもしれません。

于 2013-10-15T14:50:11.907 に答える