[英]What is the best way to get data from url and parse it on Haskell?
我在解析來自url的數據時遇到了麻煩。
我有“https://”網址,所以我想我應該使用import Network.HTTP.Conduit但是
simpleHttp url
返回L.ByteString我真的不明白在那之后我會做什么
所以我有這樣的代碼來獲取數據
toStrict1 :: L.ByteString -> B.ByteString
toStrict1 = B.concat . L.toChunks
main :: IO ()
main = do
lbs <- simpleHttp url
let page = toStrict1 lbs
和解析的例子
let lastModifiedDateTime = fromFooter $ parseTags doc
putStrLn $ "wiki.haskell.org was last modified on " ++ lastModifiedDateTime
where fromFooter = unwords . drop 6 . words . innerText . take 2 . dropWhile (~/= "<li id=footer-info-lastmod>")
我如何結合這兩部分代碼?
如您所見, simpleHttp
函數返回一個惰性字節simpleHttp
。 在TagSoup中有幾種方法可以解決這個問題。
首先,事實證明你可以直接解析它。 函數parseTags
具有簽名:
parseTags :: StringLike str => str -> [Tag str]
這意味着它可以使用StringLike
實例解析任何類型的str
,如果你查看Text.StringLike
模塊文檔,你會看到lazy ByteStrings
有一個StringLike
實例。
但是,如果你走這條路,你需要知道在ByteString
世界中所有東西都被“困住”了,所以你必須使用與字節unwords
兼容的words
和words
等函數版本編寫代碼,甚至你的putStrLn
需要適配器。 一個完整的工作示例如下所示:
import Network.HTTP.Conduit
import Text.HTML.TagSoup
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.Char8 as CL
main :: IO ()
main = do
lbs <- simpleHttp "https://wiki.haskell.org"
let lastModifiedDateTime = fromFooter $ parseTags lbs
putStrLn $ "wiki.haskell.org was last modified on "
++ CL.unpack lastModifiedDateTime
where fromFooter = CL.unwords . drop 6 . CL.words
. innerText . take 2 . dropWhile (~/= "<li id=footer-info-lastmod>")
它工作正常:
> main
wiki.haskell.org was last modified on 9 September 2013, at 22:38.
>
Data.ByteString.Lazy.Char8
的函數基本上假設Data.ByteString.Lazy.Char8
是ASCII編碼的,這足以讓這個例子工作。
但是,將基於正確字符編碼的字節串解碼為有效文本類型會更加健壯。 Haskell中的兩個主要文本類型是默認的String
類型,它效率低且速度慢,但易於使用,而Text
類型則高效但有點復雜。 (像ByteString
一樣,你需要使用Text
兼容的函數版本,比如words
等。) String
和Text
都有StringLike
實例,因此它們都可以與TagSoup一起使用。
如果我們要編寫生產質量代碼,我們實際上會查詢HTTP請求中的響應頭和/或檢查HTML中的<meta>
標記以確定實際編碼。 但是,如果我們假設編碼是UTF-8(它是), Text
版本看起來像這樣:
import Network.HTTP.Conduit
import Text.HTML.TagSoup
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
import qualified Data.ByteString.Lazy as BL
main :: IO ()
main = do
lbs <- simpleHttp "https://wiki.haskell.org"
let lastModifiedDateTime = fromFooter $ parseTags (TL.decodeUtf8 lbs)
putStrLn $ "wiki.haskell.org was last modified on "
++ TL.unpack lastModifiedDateTime
where fromFooter = TL.unwords . drop 6 . TL.words
. innerText . take 2 . dropWhile (~/= "<li id=footer-info-lastmod>")
使用utf8-string
包中的Data.ByteString.Lazy.UTF8
的String
版本如下所示:
import Network.HTTP.Conduit
import Text.HTML.TagSoup
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.UTF8 as BL
main :: IO ()
main = do
lbs <- simpleHttp "https://wiki.haskell.org"
let lastModifiedDateTime = fromFooter $ parseTags (BL.toString lbs)
putStrLn $ "wiki.haskell.org was last modified on "
++ lastModifiedDateTime
where fromFooter = unwords . drop 6 . words
. innerText . take 2 . dropWhile (~/= "<li id=footer-info-lastmod>")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.