Created
September 5, 2021 14:35
-
-
Save maralorn/a288329af50955dff353e5529f377488 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE OverloadedStrings #-} | |
{-# LANGUAGE QuasiQuotes #-} | |
{-# OPTIONS_GHC -Wall #-} | |
-- This script fetches prices of commodities like funds, etfs, stocks and | |
-- currencies by scraping a webpage and prints it in hledger compatible format. | |
module Main where | |
import Data.ByteString (ByteString) | |
import Data.String.Interpolate (i) -- dependency: string-interpolate (You could do this without it, but it’s super convenient.) | |
import Data.Text (Text) | |
import Data.Time (defaultTimeLocale, formatTime, getZonedTime) | |
-- dependencies: req, tagsoup | |
import Network.HTTP.Req (GET (GET), NoReqBody (NoReqBody), Scheme (Https), Url, bsResponse, defaultHttpConfig, https, req, responseBody, runReq, (/:)) | |
import Text.HTML.TagSoup (Tag, innerText, parseTags, (~/=)) | |
fetchPrice :: (Url scheme, Text, Text, [Tag ByteString] -> ByteString) -> IO () | |
fetchPrice (url, name, currency, scraper) = do | |
response <- runReq defaultHttpConfig $ req GET url NoReqBody bsResponse mempty | |
let tags = parseTags $ responseBody response | |
time <- getZonedTime | |
putStrLn [i|P #{formatTime defaultTimeLocale "%Y-%m-%d" time} "#{name}" #{scraper tags}#{currency}|] | |
-- See https://hackage.haskell.org/package/req-3.9.1/docs/Network-HTTP-Req.html#t:Url for how to build an URL. | |
-- You might need to modify the call to `req` in `fetchPrice` to pass "?foo=bar" parameters. | |
tagesschauURL :: Text -> Url 'Https | |
tagesschauURL name = https "www.tagesschau.de" /: "wirtschaft" /: "boersenkurse" /: name /: "" | |
-- See https://hackage.haskell.org/package/tagsoup for how to write a parser for prices from other webpages. | |
getTagesschauPrice :: [Tag ByteString] -> ByteString | |
getTagesschauPrice = innerText . take 2 . dropWhile (~/= ("<span class=\"price\">" :: String)) | |
-- Modify this list to list the commodity prices you need. | |
-- [(urltofetch, nameOfCommodity, currencyOfCommodity, tagsoupFilterToScrapePrice)] | |
-- | |
-- For tagesschauURL go to www.tagesschau.de search for your commodity and take the last part of the url | |
prices :: [(Url 'Https, Text, Text, [Tag ByteString] -> ByteString)] | |
prices = | |
[ (tagesschauURL "lu0629459743-9922402", "A1JA1R", "€", getTagesschauPrice) | |
, (tagesschauURL "xc0009666410-25216210", "$", "€", getTagesschauPrice) | |
] | |
main :: IO () | |
main = mapM_ fetchPrice prices |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment