2015-12-16 4 views
4

Я пытаюсь разобрать a ссылки из основной части (<article>) сообщения в блоге. Я адаптировал то, что нашел на FPComplete, но ничего не распечатано. (Код не работает, насколько я могу видеть, как его запускать в онлайн-среде IDE и с целью Bing также не создает ссылок.)Parsing html in haskell

В GHCI я могу имитировать первую строку parseAF, и это дает мне большой запись, которую я считаю правильным. Но cursor $// findNodes &| extractData возвращает []

Я пробовал регулярное выражение, но это было недовольно, пытаясь найти такой длинный фрагмент текста.

Может ли кто-нибудь помочь?

{-# LANGUAGE OverloadedStrings #-} 

module HtmlParser where 

import Network.HTTP.Conduit (simpleHttp) 
import Prelude hiding (concat, putStrLn) 
import Data.Text (concat) 
import Data.Text.IO (putStrLn) 
import Text.HTML.DOM (parseLBS) 
import Text.XML.Cursor (Cursor, attribute, element, fromDocument, ($//), (&//), (&/), (&|)) 

-- The URL we're going to search 
url = "http://www.amsterdamfoodie.nl/2015/wine-beer-food-restaurants-troost/" 

-- The data we're going to search for 
findNodes :: Cursor -> [Cursor] 
findNodes = element "article" &/ element "a" 

-- Extract the data from each node in turn 
extractData = concat . attribute "href" 

cursorFor :: String -> IO Cursor 
cursorFor u = do 
    page <- simpleHttp u 
    return $ fromDocument $ parseLBS page 

-- Process the list of data elements 
processData = mapM_ putStrLn 

-- main = do 
parseAF :: IO() 
parseAF = do 
    cursor <- cursorFor url 
    processData $ cursor $// findNodes &| extractData 

UPDATE После более исследуя его, кажется, что проблема заключается в element "article". Если я заменил это на element "p", в этом случае это нормально, так как в любом случае p s находятся в article, тогда я получаю свои ссылки. Довольно странно .... !!

+2

Если я ищу источник для этого сайта, то только тег '

' на самом деле не содержит ссылок в нем, похоже, что он фактически заполняется javascript, который запускается после загрузки HTML. – bheklilr

+0

Eh No. '

' работает от строки 185 до 267 и включает в себя множество ссылок - некоторые в тексте и некоторые обернуты wordpress вокруг изображений (которые мне на самом деле не нужны) –

+0

А, да, вы выглядели бы правильно. Можете ли вы проверить, что, когда вы загружаете его с помощью 'simpleHttp', вы получаете один и тот же контент? Я бы попробовал это сам, но сейчас я за корпоративным прокси, что затрудняет это. – bheklilr

ответ

3

Я думаю, что вы можете сделать это в очень понятным способом с HXT сочинением фильтрами:

{-# LANGUAGE Arrows #-} 

import Text.XML.HXT.Core 
import Text.XML.HXT.Curl 
import Text.XML.HXT.TagSoup 

links url = extract (readDocument 
    [ withParseHTML yes 
    , withTagSoup 
    , withCurl  [] 
    , withWarnings no 
    ] url) 

extract doc = runX $ doc >>> xmlFilter "article" >>> xmlFilter "a" >>> toHref 

xmlFilter name = deep (hasName name) 

toHref = proc el -> do 
    link <- getAttrValue "href" -< el 
    returnA -< link 

Вы можете назвать это следующим образом:

links "http://www.amsterdamfoodie.nl/2015/wine-beer-food-restaurants-troost/" 
+0

Предположим, что html соответствует xml? – doron

+1

Поскольку параметр «withParseHTML» установлен, вместо парсера XML используется парсер HTML. Таким образом, предполагается, что он является допустимым HTML. –

+1

Немного более читаемый, все еще с избыточными родителями в 'extractLinks' удален. –

1

ОК, так что проблема была что &/ смотрит только на непосредственных детей, в то время как &// будет проходить через все потомки

findNodes = element "article" &// element "a"