2017-06-22 12 views
0

私は、WebサイトのHTMLコードを通過し、同じベースURL(同じサイトのWebページを参照)を含むすべてのリンクを返すリンクアナライザと、現在imこのコードをまとめてください。 (私は初心者ですので^^素人コードでご負担ください):再帰的に別の関数を実行する再帰関数を実装する

import Network.HTTP 
import Data.List 
import Data.Char 

htmlLinks link = do 
    content <- simpleHTTP (getRequest link) >>= fmap (take 10000) . getResponseBody 
    let string = content 
    let tags = splitOn "<" string 
    let links = filter (isInfixOf "href") tags 
    let filtered = filter (isInfixOf link) links 
    let url = map (splitOn "\"") filtered 
    let final = map (filter (isInfixOf "http")) url 
    let urlString = map (\(h:_) -> h)final 
    let result = nub urlString 
    --let result = map head $ group $ sort urlString 
    return result 

この関数は、コードを通過し、私が欲しい同じベースURLを持つすべてのリンクのリストを返します。今、私はそのリストの各要素を調べ、同じ機能をそれらに適用したいので、それらのサイトのそれぞれにリンクをもらって、最終的に私に特定のウェブサイト構造のすべてのウェブページを提供することができます。だから私はこれを試してみました再帰関数のために:

linkScanner result = linkRec [] result where 
    linkRec acc [] = acc 
    linkRec acc (h:t) = linkRec ((htmlLinks h) : acc) t 

この基本的に各要素にhtmlLinksを適用し、この場合には空のリストである私のアキュムレータにその結果を追加するリンクのリストを取ります。今私の問題は、これらの2つの関数を組み合わせて、指定されたURLで実行し、必要なすべてのリンクのリストを提供できる方法を見つけることができないことです。 htmlLinksがタイプIO [文字列]で、再帰関数にエラーが発生する[文字列]が必要なため、型の競合もあります。

この問題の解決方法やヒントを探しています私が望む結果に到達するために使うことができるもの。すべての助けが大歓迎です!

+0

ResponseBodyのfmap(take 10000)をテスト用に追加すると、htmlコードの小さなチャックで作業できるようになります。後で削除されます。 –

答えて

0

はおそらくところで(逆の順序でリストを返します)

linkScanner result = linkRec [] result where 
linkRec acc [] = return acc 
linkRec acc (h:t) = do 
    x <- htmlLinks h 
    linkRec (x : acc) t 

または

linkScanner = traverse htmlLinks -- or the analogous with mapM 

のようなものは、あなたが本当にトップレベルのバインディングに型注釈を追加する必要がありますしたいです。そうでなければ何が起こっているのか考えるのはとても難しいです。

+0

それでコード自体はIO文字列で動作するでしょうか?原因は、問題/エラーと思われる..私はリンクスキャナ機能を意味します。ご協力いただきありがとうございます! –

+0

@ M.Oそれはすべきです。 – chi