目录

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

目录

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

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

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

https://i-blog.csdnimg.cn/direct/51f3c5e46a2f4fa1b25aa4e3c94a2e46.png#pic_center

1、安装 wreqhttp-client

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

cabal update
cabal install wreq

2、、导入必要模块

在 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 代理服务器来发送请求,首先需要配置代理:

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 提取响应体中的内容。以下是一个抓取网页内容并打印响应的简单例子:

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 数据,并解析它:

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 数据:

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