簡體   English   中英

從url獲取數據並在Haskell上解析它的最佳方法是什么?

[英]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兼容的wordswords等函數版本編寫代碼,甚至你的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等。) StringText都有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.UTF8String版本如下所示:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM