2

昨天我尝试在Network.HTTPFeed库的帮助下在 Haskell 中编写一个简单的 rss 下载器。我想从 rss 项目下载链接,并在项目标题后命名下载的文件。

这是我的短代码:

import Control.Monad
import Control.Applicative
import Network.HTTP
import Text.Feed.Import
import Text.Feed.Query
import Text.Feed.Types
import Data.Maybe
import qualified Data.ByteString as B
import Network.URI (parseURI, uriToString)

getTitleAndUrl :: Item -> (Maybe String, Maybe String)
getTitleAndUrl item = (getItemTitle item, getItemLink item)

downloadUri :: (String,String) -> IO ()
downloadUri (title,link) = do
  file <- get link
  B.writeFile title file
    where
      get url = let uri = case parseURI url of
                      Nothing -> error $ "invalid uri" ++ url
                      Just u -> u in
                simpleHTTP (defaultGETRequest_ uri) >>= getResponseBody

getTuples :: IO (Maybe [(Maybe String, Maybe String)])
getTuples = fmap (map getTitleAndUrl) <$> fmap (feedItems) <$> parseFeedString <$> (simpleHTTP (getRequest "http://index.hu/24ora/rss/") >>= getResponseBody)

我达到了一个状态,我得到了一个包含元组的列表,其中包含名称和相应的链接。而且我有一个downloadUri功能,可以将给定的链接正确下载到具有 rss 项目标题名称的文件中。

我已经尝试修改以继续downloadUri工作,但失败了。(Maybe String,Maybe String)fmapgetwriteFile

  • 我如何将我downloadUri的函数应用于函数的结果getTuples。我想实现以下主要功能

    main :: IO ()
    main = some magic incantation donwloadUri more incantation getTuples

  • 破碎结果的字符编码getItemTitle,它把代码点放在重音字符的地方。提要是utf8编码的,我认为所有haskell字符串操作函数都默认为utf8。我怎样才能解决这个问题?

编辑:

感谢您的帮助,我成功实现了我的主要功能和辅助功能。代码如下:

downloadUri :: (Maybe String,Maybe String) -> IO ()
downloadUri (Just title,Just link) = do
  item <- get link
  B.writeFile title item
    where
      get url = let uri = case parseURI url of
                      Nothing -> error $ "invalid uri" ++ url
                      Just u -> u in
                simpleHTTP (defaultGETRequest_ uri) >>= getResponseBody
downloadUri _ = print "Somewhere something went Nothing"

getTuples :: IO (Maybe [(Maybe String, Maybe String)])
getTuples = fmap (map getTitleAndUrl) <$> fmap (feedItems) <$> parseFeedString <$> decodeString <$> (simpleHTTP (getRequest "http://index.hu/24ora/rss/") >>= getResponseBody)

downloadAllItems :: Maybe [(Maybe String, Maybe String)] -> IO ()
downloadAllItems (Just feedlist) = mapM_ downloadUri $ feedlist
downloadAllItems _ = error "feed does not get parsed"

main = getTuples >>= downloadAllItems

字符编码问题已部分解决,我放在decodeString提要解析之前,因此文件被正确命名。但是如果我想打印出来,问题仍然存在。最小的工作示例:

main = getTuples
4

2 回答 2

2

听起来好像是Maybes 给你带来了麻烦。处理值的方法有很多Maybe,还有一些有用的库函数,如fromMaybefromJust。但是,最简单的方法是对Maybe值进行模式匹配。我们可以调整您的 downloadUri 函数以使用这些Maybe值。这是一个例子:

downloadUri :: (Maybe String, Maybe String) -> IO ()
downloadUri (Just title, Just link) = do
  file <- get link
  B.writeFile title file
    where
      get url = let uri = case parseURI url of
                      Nothing -> error $ "invalid uri" ++ url
                      Just u -> u in
                simpleHTTP (defaultGETRequest_ uri) >>= getResponseBody
downloadUri _ = error "One of my parameters was Nothing".

或者您可以让标题默认为空白,在这种情况下,您可以在上一个示例的最后一行之前插入它:

downloadUri (Nothing, Just link) = downloadUri (Just "", Just link)

现在Maybe你唯一需要处理的是外部的,应用于元组数组。同样,我们可以进行模式匹配。编写这样的辅助函数可能是最清楚的:

downloadAllItems (Just ts) = ??? -- hint: try a `mapM`
downloadAllItems Nothing = ??? -- don't do anything, or report an error, or...

至于您的编码问题,我的猜测是:

  1. 您正在从不是 UTF-8 编码的文件中读取信息,或者您的系统没有意识到它是 UTF-8 编码的。
  2. 您正在正确阅读信息,但是当您输出它时它会变得混乱。

为了帮助您解决这个问题,我需要查看一个完整的代码示例,它显示了您如何阅读信息以及如何输出信息。

于 2013-06-11T12:25:27.457 回答
1

您的主要内容可能如下所示。不过,可能有一些更简洁的方法来组合这两个操作:

main :: IO ()
main = getTuples >>= process
       where
           process (Just lst) = foldl (\s v -> do {t <- s; download v}) (return ()) lst 
           process Nothing = return ()
           download (Just t, Just l) = downloadUri (t,l)
           download _ = return ()
于 2013-06-11T09:05:27.030 回答