{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
module Scrappy.Scrape where
import Scrappy.Elem.Types (Elem', innerText')
import Scrappy.Elem.ElemHeadParse (hrefParser, parseOpeningTag)
import Scrappy.Elem.SimpleElemParser (el)
import Scrappy.Elem.ChainHTML ((</>>))
import Scrappy.Find (findNaive, findNaiveIO)
import Scrappy.Links (maybeUsefulUrl)
import Scrappy.Types
import Control.Monad.Trans.Maybe (MaybeT(..))
import Control.Monad.IO.Class (MonadIO)
import Data.Functor.Identity (Identity)
import Data.Either (fromRight)
import Data.Maybe (catMaybes, fromMaybe)
import Text.Parsec (Stream, ParsecT, parse, string, parserZero, anyChar, manyTill, char, many, try, runParserT)
import Control.Applicative (liftA2)
type ScraperT a = ParsecT Html () Identity a
scrapeLinked :: ParsecT s u m a -> ParsecT s u m [String]
scrapeLinked :: forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m [String]
scrapeLinked = ParsecT s u m a -> ParsecT s u m [String]
forall a. HasCallStack => a
undefined
filterFromTextP :: ScraperT a -> ScraperT String
filterFromTextP :: forall a. ScraperT a -> ScraperT String
filterFromTextP ScraperT a
p = (ScraperT a -> ParsecT String () Identity [a]
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (ScraperT a -> ScraperT a
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ScraperT a
p)) ParsecT String () Identity [a]
-> ScraperT String -> ScraperT String
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ((Char -> String -> String)
-> ParsecT String () Identity Char
-> ScraperT String
-> ScraperT String
forall a b c.
(a -> b -> c)
-> ParsecT String () Identity a
-> ParsecT String () Identity b
-> ParsecT String () Identity c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (:) ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar (ScraperT a -> ScraperT String
forall a. ScraperT a -> ScraperT String
filterFromTextP ScraperT a
p))
filterPattern :: String -> ScraperT a -> String
filterPattern :: forall a. String -> ScraperT a -> String
filterPattern String
txt ScraperT a
p = (ParseError -> String)
-> (String -> String) -> Either ParseError String -> String
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ParseError -> String
forall a. HasCallStack => a
undefined String -> String
forall a. a -> a
id (Either ParseError String -> String)
-> Either ParseError String -> String
forall a b. (a -> b) -> a -> b
$ ScraperT String -> String -> String -> Either ParseError String
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (ScraperT a -> ScraperT String
forall a. ScraperT a -> ScraperT String
filterFromTextP ScraperT a
p) String
"" String
txt
coerceMaybeParser :: Maybe a -> ScraperT a
coerceMaybeParser :: forall a. Maybe a -> ScraperT a
coerceMaybeParser = \case
Just a
a -> a -> ScraperT a
forall a. a -> ParsecT String () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
Maybe a
Nothing -> ScraperT a
forall s u (m :: * -> *) a. ParsecT s u m a
parserZero
hoistMaybe :: Applicative m => Maybe a -> MaybeT m a
hoistMaybe :: forall (m :: * -> *) a. Applicative m => Maybe a -> MaybeT m a
hoistMaybe = m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a)
-> (Maybe a -> m (Maybe a)) -> Maybe a -> MaybeT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe a -> m (Maybe a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
exists :: ScraperT a -> Html -> Bool
exists :: forall a. ScraperT a -> String -> Bool
exists ScraperT a
p String
html = Bool -> ([a] -> Bool) -> Maybe [a] -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Bool -> [a] -> Bool
forall a b. a -> b -> a
const Bool
True) (Maybe [a] -> Bool) -> Maybe [a] -> Bool
forall a b. (a -> b) -> a -> b
$ ScraperT a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml ScraperT a
p String
html
scrape :: ScraperT a -> Html -> Maybe [a]
scrape :: forall a. ParsecT String () Identity a -> String -> Maybe [a]
scrape = ParsecT String () Identity a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml
scrapeFirst' :: ScraperT a -> Html -> Maybe a
scrapeFirst' :: forall a. ScraperT a -> String -> Maybe a
scrapeFirst' ScraperT a
f String
h = case ScraperT a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
scrape ScraperT a
f String
h of
Just (a
x:[a]
xs) -> a -> Maybe a
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
Maybe [a]
_ -> Maybe a
forall a. Maybe a
Nothing
getFirstSafe :: Maybe [a] -> Maybe a
getFirstSafe :: forall a. Maybe [a] -> Maybe a
getFirstSafe (Just (a
x:[a]
_)) = a -> Maybe a
forall a. a -> Maybe a
Just a
x
getFirstSafe Maybe [a]
_ = Maybe a
forall a. Maybe a
Nothing
getFirstFitSafe :: (a -> Bool) -> Maybe [a] -> Maybe a
getFirstFitSafe :: forall a. (a -> Bool) -> Maybe [a] -> Maybe a
getFirstFitSafe a -> Bool
f (Just (a
x:[a]
xs)) = (a -> Bool) -> [a] -> Maybe a
forall a. (a -> Bool) -> [a] -> Maybe a
findFit a -> Bool
f (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs)
getFirstFitSafe a -> Bool
_ Maybe [a]
_ = Maybe a
forall a. Maybe a
Nothing
findFit :: (a -> Bool) -> [a] -> Maybe a
findFit :: forall a. (a -> Bool) -> [a] -> Maybe a
findFit a -> Bool
_ [] = Maybe a
forall a. Maybe a
Nothing
findFit a -> Bool
cond (a
x:[a]
xs) = if a -> Bool
cond a
x then a -> Maybe a
forall a. a -> Maybe a
Just a
x else (a -> Bool) -> [a] -> Maybe a
forall a. (a -> Bool) -> [a] -> Maybe a
findFit a -> Bool
cond [a]
xs
runScraperOnHtml :: ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml :: forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml ParsecT String () Identity a
p String
html = Maybe [a] -> Either ParseError (Maybe [a]) -> Maybe [a]
forall b a. b -> Either a b -> b
fromRight Maybe [a]
forall a. Maybe a
Nothing (Either ParseError (Maybe [a]) -> Maybe [a])
-> Either ParseError (Maybe [a]) -> Maybe [a]
forall a b. (a -> b) -> a -> b
$ Parsec String () (Maybe [a])
-> String -> String -> Either ParseError (Maybe [a])
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (ParsecT String () Identity a -> Parsec String () (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive (ParsecT String () Identity a -> Parsec String () (Maybe [a]))
-> ParsecT String () Identity a -> Parsec String () (Maybe [a])
forall a b. (a -> b) -> a -> b
$ ParsecT String () Identity a
p) String
"" String
html
runScraperOnHtmlIO :: (MonadIO m, Show a, Stream String m Char) => ParsecT String () m a -> String -> m (Maybe [a])
runScraperOnHtmlIO :: forall (m :: * -> *) a.
(MonadIO m, Show a, Stream String m Char) =>
ParsecT String () m a -> String -> m (Maybe [a])
runScraperOnHtmlIO ParsecT String () m a
p String
html = do
Either ParseError (Maybe [a])
x <- ParsecT String () m (Maybe [a])
-> () -> String -> String -> m (Either ParseError (Maybe [a]))
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> u -> String -> s -> m (Either ParseError a)
runParserT (ParsecT String () m a -> ParsecT String () m (Maybe [a])
forall (m :: * -> *) s a u.
(MonadIO m, Stream s m Char, Show a) =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaiveIO (ParsecT String () m a -> ParsecT String () m (Maybe [a]))
-> ParsecT String () m a -> ParsecT String () m (Maybe [a])
forall a b. (a -> b) -> a -> b
$ ParsecT String () m a
p) () String
"" String
html
Maybe [a] -> m (Maybe [a])
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe [a] -> m (Maybe [a])) -> Maybe [a] -> m (Maybe [a])
forall a b. (a -> b) -> a -> b
$ Maybe [a] -> Either ParseError (Maybe [a]) -> Maybe [a]
forall b a. b -> Either a b -> b
fromRight Maybe [a]
forall a. Maybe a
Nothing Either ParseError (Maybe [a])
x
scrapeIO :: (MonadIO m, Show a, Stream String m Char) => ParsecT String () m a -> String -> m (Maybe [a])
scrapeIO :: forall (m :: * -> *) a.
(MonadIO m, Show a, Stream String m Char) =>
ParsecT String () m a -> String -> m (Maybe [a])
scrapeIO = ParsecT String () m a -> String -> m (Maybe [a])
forall (m :: * -> *) a.
(MonadIO m, Show a, Stream String m Char) =>
ParsecT String () m a -> String -> m (Maybe [a])
runScraperOnHtmlIO
runScraperInBody :: ParsecT String () Identity a -> String -> Maybe [a]
runScraperInBody :: forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperInBody ParsecT String () Identity a
prsr String
html = Maybe [a] -> Either ParseError (Maybe [a]) -> Maybe [a]
forall b a. b -> Either a b -> b
fromRight Maybe [a]
forall a. Maybe a
Nothing (Either ParseError (Maybe [a]) -> Maybe [a])
-> Either ParseError (Maybe [a]) -> Maybe [a]
forall a b. (a -> b) -> a -> b
$ Parsec String () (Maybe [a])
-> String -> String -> Either ParseError (Maybe [a])
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
skipToInBody ParsecT String () Identity ()
-> Parsec String () (Maybe [a]) -> Parsec String () (Maybe [a])
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT String () Identity a -> Parsec String () (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive ParsecT String () Identity a
prsr) String
"" String
html
skipToInBody :: Stream s m Char => ParsecT s u m ()
skipToInBody :: forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
skipToInBody = ParsecT s u m Char -> ParsecT s u m Char -> ParsecT s u m String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill ParsecT s u m Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar (Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
forall s (m :: * -> *) u.
Stream s m Char =>
Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
parseOpeningTag ([String] -> Maybe [String]
forall a. a -> Maybe a
Just [String
"html"]) [] ParsecT s u m (String, Attrs)
-> ParsecT s u m Char -> ParsecT s u m Char
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>')
ParsecT s u m String
-> ParsecT s u m (Elem' String) -> ParsecT s u m (Elem' String)
forall s (m :: * -> *) u a b.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
</>> String -> [(String, String)] -> ParsecT s u m (Elem' String)
forall s (m :: * -> *) u.
Stream s m Char =>
String -> [(String, String)] -> ParsecT s u m (Elem' String)
el String
"head" []
ParsecT s u m (Elem' String)
-> ParsecT s u m (String, Attrs) -> ParsecT s u m (String, Attrs)
forall s (m :: * -> *) u a b.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
</>> Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
forall s (m :: * -> *) u.
Stream s m Char =>
Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
parseOpeningTag ([String] -> Maybe [String]
forall a. a -> Maybe a
Just [String
"body"]) []
ParsecT s u m (String, Attrs)
-> ParsecT s u m Char -> ParsecT s u m Char
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>'
ParsecT s u m Char -> ParsecT s u m () -> ParsecT s u m ()
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> ParsecT s u m ()
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
runScraperOnBody :: ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnBody :: forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnBody ParsecT String () Identity a
prsr String
html = Maybe [a] -> Either ParseError (Maybe [a]) -> Maybe [a]
forall b a. b -> Either a b -> b
fromRight Maybe [a]
forall a. Maybe a
Nothing (Either ParseError (Maybe [a]) -> Maybe [a])
-> Either ParseError (Maybe [a]) -> Maybe [a]
forall a b. (a -> b) -> a -> b
$ Parsec String () (Maybe [a])
-> String -> String -> Either ParseError (Maybe [a])
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
skipToBody ParsecT String () Identity ()
-> Parsec String () (Maybe [a]) -> Parsec String () (Maybe [a])
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT String () Identity a -> Parsec String () (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive ParsecT String () Identity a
prsr) String
"" String
html
skipToBody :: Stream s m Char => ParsecT s u m ()
skipToBody :: forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
skipToBody = ParsecT s u m Char -> ParsecT s u m Char -> ParsecT s u m String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill ParsecT s u m Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar (Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
forall s (m :: * -> *) u.
Stream s m Char =>
Maybe [String]
-> [(String, Maybe String)] -> ParsecT s u m (String, Attrs)
parseOpeningTag ([String] -> Maybe [String]
forall a. a -> Maybe a
Just [String
"html"]) [] ParsecT s u m (String, Attrs)
-> ParsecT s u m Char -> ParsecT s u m Char
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>') ParsecT s u m String
-> ParsecT s u m (Elem' String) -> ParsecT s u m (Elem' String)
forall s (m :: * -> *) u a b.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
</>> String -> [(String, String)] -> ParsecT s u m (Elem' String)
forall s (m :: * -> *) u.
Stream s m Char =>
String -> [(String, String)] -> ParsecT s u m (Elem' String)
el String
"head" [] ParsecT s u m (Elem' String)
-> ParsecT s u m () -> ParsecT s u m ()
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> ParsecT s u m ()
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
runScraperOnHtml1 :: ParsecT String () Identity a -> String -> Maybe a
runScraperOnHtml1 :: forall a. ScraperT a -> String -> Maybe a
runScraperOnHtml1 ParsecT String () Identity a
p = (([a] -> a) -> Maybe [a] -> Maybe a
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [a] -> a
forall a. HasCallStack => [a] -> a
head) (Maybe [a] -> Maybe a)
-> (String -> Maybe [a]) -> String -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParsecT String () Identity a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
runScraperOnHtml ParsecT String () Identity a
p
scrapeFirst :: Stream s m Char => ParsecT s u m a -> ParsecT s u m (Maybe a)
scrapeFirst :: forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
scrapeFirst ParsecT s u m a
p = do
Maybe [a]
x <- ParsecT s u m a -> ParsecT s u m (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive ParsecT s u m a
p
case Maybe [a]
x of
Just (a
x:[a]
_) -> Maybe a -> ParsecT s u m (Maybe a)
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> ParsecT s u m (Maybe a))
-> Maybe a -> ParsecT s u m (Maybe a)
forall a b. (a -> b) -> a -> b
$ a -> Maybe a
forall a. a -> Maybe a
Just a
x
Maybe [a]
Nothing -> Maybe a -> ParsecT s u m (Maybe a)
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> ParsecT s u m (Maybe a))
-> Maybe a -> ParsecT s u m (Maybe a)
forall a b. (a -> b) -> a -> b
$ Maybe a
forall a. Maybe a
Nothing
findCount :: Stream s m Char => ParsecT s u m a -> ParsecT s u m Int
findCount :: forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m Int
findCount ParsecT s u m a
p = do
Maybe [a]
x <- ParsecT s u m a -> ParsecT s u m (Maybe [a])
forall s (m :: * -> *) u a.
Stream s m Char =>
ParsecT s u m a -> ParsecT s u m (Maybe [a])
findNaive ParsecT s u m a
p
Int -> ParsecT s u m Int
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> ParsecT s u m Int) -> Int -> ParsecT s u m Int
forall a b. (a -> b) -> a -> b
$ [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([a] -> Maybe [a] -> [a]
forall a. a -> Maybe a -> a
fromMaybe [] Maybe [a]
x)
type Prefix' = String
{-# DEPRECATED scrapeBracketed "experimental, first attempt" #-}
scrapeBracketed :: Prefix' -> ScraperT a -> Html -> Maybe [a]
scrapeBracketed :: forall a. String -> ScraperT a -> String -> Maybe [a]
scrapeBracketed String
pre ScraperT a
scraper String
html = [[a]] -> [a]
forall a. Monoid a => [a] -> a
mconcat ([[a]] -> [a]) -> Maybe [[a]] -> Maybe [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ScraperT [a] -> String -> Maybe [[a]]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
scrape (String -> ScraperT String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
pre ScraperT String -> ScraperT [a] -> ScraperT [a]
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ScraperT a -> ScraperT String -> ScraperT [a]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill ScraperT a
scraper (String -> ScraperT String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
pre)) String
html
type Prefix = String
scrapePrefixed :: Prefix -> ScraperT a -> Html -> Maybe [a]
scrapePrefixed :: forall a. String -> ScraperT a -> String -> Maybe [a]
scrapePrefixed String
pre ScraperT a
scraper String
html = ScraperT a -> String -> Maybe [a]
forall a. ParsecT String () Identity a -> String -> Maybe [a]
scrape (String -> ScraperT String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
pre ScraperT String -> ScraperT a -> ScraperT a
forall a b.
ParsecT String () Identity a
-> ParsecT String () Identity b -> ParsecT String () Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ScraperT a
scraper) String
html