用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 请求支持、错误处理等。

相关推荐
yleihj9 小时前
vCenter计算机SSL证书续期
服务器·网络协议·ssl
lifewange9 小时前
https和http有什么区别
网络协议·http·https
空中海10 小时前
5.1 HTTP 与网络请求
网络·网络协议·flutter·http
Flash.kkl12 小时前
应用层协议HTTP
网络·网络协议·http
lew-yu13 小时前
websocket后端实现心跳检测,并定时清理异常的连接
websocket·网络协议·vim
达不溜的日记13 小时前
CAN总线网络传输层CanTp详解
网络·stm32·嵌入式硬件·网络协议·网络安全·信息与通信·信号处理
wanhengidc13 小时前
网站服务器具体功能有哪些?
运维·服务器·网络·网络协议·智能手机
千枫s14 小时前
做一个电脑版爬虫程序
爬虫·python
杨凯凡15 小时前
【006】常见 WebSocket 场景与后端 session/鉴权的关系
网络·websocket·网络协议
亿牛云爬虫专家15 小时前
生产级Go高并发爬虫实战:突破 net_http 长连接与隧道代理IP切换陷阱
爬虫·http·golang·代理ip·keepalive·隧道代理·https connect