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

相关推荐
zzyh1234563 小时前
tcp/ip协议配置参数有哪些?tcp/ip协议需要设置的参数有哪些
网络协议·tcp/ip·php
无人不xiao3 小时前
WebSocket
网络·websocket·网络协议
学习嵌入式的小羊~4 小时前
远程监控项目描述以及总体框架
网络协议·http
专注VB编程开发20年5 小时前
JS采集数据爬虫-Fetch API 和 XMLHttpRequest 有什么区别?
开发语言·javascript·爬虫·js
m0_748256145 小时前
Python中的简单爬虫
爬虫·python·信息可视化
还是鼠鼠5 小时前
http 模块的概念及作用详细介绍
前端·javascript·vscode·http·node.js·web
程序员黄同学7 小时前
谈谈 HTTP 中的重定向,如何处理301和302重定向?
网络·网络协议·http
与光同尘 大道至简7 小时前
万字技术指南STM32F103C8T6 + ESP8266-01 连接 OneNet 平台 MQTT/HTTP
stm32·单片机·嵌入式硬件·物联网·http·docker·信息与通信
XiaoLeisj7 小时前
【计算机原理】深入解析 HTTP 中的 URL 格式、结构和 URL encode 转义与 URL decode 逆转义原理
网络·网络协议·tcp/ip·http·fiddler·信息与通信
群联云防护小杜7 小时前
语音视频App协议安全实战:防御伪造/窃听/Deepfake攻击
运维·服务器·爬虫·安全·web安全·音视频