Разбор HTML в Haskell

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

В 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

ОБНОВЛЕНИЕ После дальнейшего изучения кажется, что проблема заключается в element "article", Если я заменю это на element "p", что нормально в этом случае как единственный pс в article в любом случае, тогда я получаю свои ссылки. Довольно странно....!!

2 ответа

Я думаю, что вы можете сделать это очень легко читаемым способом с помощью 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/"

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

findNodes = element "article" &// element "a"
Другие вопросы по тегам