用Haskell语言和wreq库配合HTTP写个爬虫程序

在 Haskell 中,wreq 库是一个非常方便的 HTTP 请求库,适合用来编写爬虫程序。你可以使用它来发送 GET 或 POST 请求,抓取网页内容,处理响应数据等。我们可以结合 HTTP 代理配置来实现网络请求。

下面我将展示如何在 Haskell 中使用 wreq 库配合 HTTP 请求编写一个爬虫程序。

1、安装 wreqhttp-client

首先,确保你已安装 wreq 库。你可以通过 cabal 安装它。wreq 依赖于 http-clienthttp-client-tls 库,因此需要一起安装。

bash 复制代码
cabal update
cabal install wreq

2、、导入必要模块

在 Haskell 中,我们需要导入以下模块:

haskell 复制代码
import Control.Lens
import Network.Wreq
import qualified Data.ByteString.Lazy.Char8 as L8
import Network.HTTP.Client (newManager, defaultManagerSettings)
import Network.Wreq.Session (withSession)
import Data.Aeson
  • Control.Lens: 用于从 HTTP 请求和响应中提取数据。
  • Network.Wreq: 提供了发送 HTTP 请求的功能。
  • Data.ByteString.Lazy.Char8: 用于处理响应的字节流。
  • Network.HTTP.Client: 负责创建 HTTP 客户端和配置代理。
  • Network.Wreq.Session: 用于创建带有会话状态的请求,适合需要持续会话的爬虫任务。

3、设置 HTTP 代理

假设你需要使用 HTTP 代理服务器来发送请求,首先需要配置代理:

haskell 复制代码
import Network.Wreq
import Network.HTTP.Client (newManager, defaultManagerSettings, managerModifyRequest)
import Network.HTTP.Client.TLS (tlsManagerSettings)

-- 设置 HTTP 代理
setupProxy :: IO Manager
setupProxy = do
  manager <- newManager tlsManagerSettings
  return $ managerModifyRequest manager $ \req -> do
    let proxy = "http://localhost:8080"  -- 代理地址
    setRequestProxy proxy req

在上面的代码中,我们创建了一个 setupProxy 函数,它将设置代理服务器地址。你可以根据实际需要修改代理的 URL。

4、发送 HTTP 请求并获取网页内容

我们将通过 wreq 库发送 HTTP 请求,抓取网页内容,并使用 Lens 提取响应体中的内容。以下是一个抓取网页内容并打印响应的简单例子:

haskell 复制代码
import Network.Wreq
import Control.Lens
import Data.ByteString.Lazy.Char8 as L8

-- 使用代理发送 GET 请求并打印网页内容
fetchPage :: IO ()
fetchPage = do
    manager <- setupProxy
    let opts = defaults & manager .~ Just manager
    response <- getWith opts "https://www.example.com"  -- 目标网页
    L8.putStrLn (response ^. responseBody)  -- 打印网页的响应体

在这个例子中,getWith 函数通过代理发送 GET 请求,并获取目标网页的响应内容。responseBody 是通过 Lens 提取响应体内容,我们将其打印到控制台。

5、处理 JSON 响应

如果你抓取的是 JSON 数据,可以使用 aeson 库来解析 JSON 响应。wreqaeson 库结合得很好,允许你直接将 JSON 响应转化为 Haskell 数据类型。

假设我们从 API 获取 JSON 数据,并解析它:

haskell 复制代码
import Network.Wreq
import Control.Lens
import Data.Aeson
import Data.Maybe (fromJust)

-- 假设我们有一个 JSON 响应,格式为:{"id": 1, "name": "example"}
data Response = Response {
    id :: Int,
    name :: String
} deriving (Show)

instance FromJSON Response where
    parseJSON = withObject "Response" $ \v -> Response
        <$> v .: "id"
        <*> v .: "name"

-- 使用代理发送 GET 请求并解析 JSON 响应
fetchJson :: IO ()
fetchJson = do
    manager <- setupProxy
    let opts = defaults & manager .~ Just manager
    response <- getWith opts "https://jsonplaceholder.typicode.com/users/1"
    
    let jsonResponse = response ^. responseBody
    let parsedData = decode jsonResponse :: Maybe Response
    case parsedData of
        Just data' -> print data'
        Nothing -> putStrLn "Failed to parse JSON"

在这个例子中,Response 是我们定义的一个数据类型,用来表示 JSON 响应的数据结构。FromJSON 实例使得我们能够从 JSON 数据中提取字段。decode 函数将 JSON 响应解析为 Response 类型。

6、完整示例:通过代理抓取网页并解析数据

最后,以下是一个完整的示例,展示如何使用 wreq 配合代理抓取网页,并解析其 JSON 数据:

haskell 复制代码
import Network.Wreq
import Control.Lens
import Network.HTTP.Client (newManager, defaultManagerSettings, managerModifyRequest)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as L8
import Data.Maybe (fromJust)

-- 设置代理
setupProxy :: IO Manager
setupProxy = do
    manager <- newManager tlsManagerSettings
    return $ managerModifyRequest manager $ \req -> do
        let proxy = "http://localhost:8080"  -- 设置代理地址
        setRequestProxy proxy req

-- 数据类型用于解析 JSON
data Response = Response {
    id :: Int,
    name :: String
} deriving (Show)

instance FromJSON Response where
    parseJSON = withObject "Response" $ \v -> Response
        <$> v .: "id"
        <*> v .: "name"

-- 使用代理发送 GET 请求并解析 JSON
fetchJson :: IO ()
fetchJson = do
    manager <- setupProxy
    let opts = defaults & manager .~ Just manager
    response <- getWith opts "https://jsonplaceholder.typicode.com/users/1"
    
    -- 解析 JSON 响应
    let jsonResponse = response ^. responseBody
    let parsedData = decode jsonResponse :: Maybe Response
    case parsedData of
        Just data' -> print data'
        Nothing -> putStrLn "Failed to parse JSON"

main :: IO ()
main = fetchJson

7、总结

在这个 Haskell 示例中,我们展示了如何使用 wreq 库配合 HTTP 代理进行网络请求,并抓取网页内容或 API 返回的 JSON 数据。主要步骤包括:

  1. 配置 HTTP 代理。
  2. 使用 wreq 发送 HTTP 请求。
  3. 使用 Lens 提取响应体内容。
  4. 使用 Aeson 库解析 JSON 数据。

我们可以根据需要扩展这个爬虫程序,添加更多的请求头、POST 请求支持、错误处理等。

相关推荐
青春给了代码1 小时前
基于WebSocket实现在线语音(实时+保存)+文字双向传输完整实现
网络·websocket·网络协议
北京耐用通信1 小时前
破解AGV多协议互联难题:耐达讯自动化Profinet转Devicenet网关如何实现高效协同
人工智能·科技·物联网·网络协议·自动化·信息与通信
喵手2 小时前
Python爬虫实战:公共自行车站点智能采集系统 - 从零构建生产级爬虫的完整实战(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·采集公共自行车站点·公共自行车站点智能采集系统·采集公共自行车站点导出csv
喵手2 小时前
Python爬虫实战:地图 POI + 行政区反查实战 - 商圈热力数据准备完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·地区poi·行政区反查·商圈热力数据采集
win x2 小时前
深入理解HTTPS协议加密流程
网络协议·http·https
仙俊红2 小时前
从 Filter / Interceptor 到 HTTPS
网络协议·http·https
芷栀夏2 小时前
从 CANN 开源项目看现代爬虫架构的演进:轻量、智能与统一
人工智能·爬虫·架构·开源·cann
liann1192 小时前
3.1_网络——基础
网络·安全·web安全·http·网络安全
全栈工程师修炼指南3 小时前
Nginx | stream 四层反向代理:SSL、PREREAD 阶段模块指令浅析与实践
运维·网络·网络协议·nginx·ssl
极新3 小时前
智启新篇,智创未来,“2026智造新IP:AI驱动品牌增长新周期”峰会暨北京电子商务协会第五届第三次会员代表大会成功举办
人工智能·网络协议·tcp/ip