haskell - 使用 Haskell 进行 Web 抓取循环
问题描述
我想学习 Haskell,并且我有另一个小项目(目前在 Elixir 中),我想将其移植为练习。这是一个简单的网络抓取工具,可以抓取 url 列表。
想象一下,有一个邮政编码列表,大约有 2500 个项目。对于每个条目,应抓取一个网页,格式为http://www.acme.org/zip-info?zip={ZIP}
. 我设法编写了使用 Scalpel 抓取单个网页的代码。
但是我将如何去刮掉 2500 件物品呢?在 Elixir 中,我映射了邮政编码列表,在每个页面请求之后,都会有 1 秒的短暂睡眠,以减轻目标网站的压力。对我来说,尽可能快地抓取网站并不重要。
我将如何在 Haskell 中执行此操作?我读到了,threadSleep
但是我如何结合使用列表来遍历和主要方法,因为睡眠是副作用。
感谢您的见解!
解决方案
大概你已经有一个功能,如:
scrapeZip :: Zip -> IO ZipResult
然后您可以编写一个函数traverse
来获取一个返回 zip 结果列表的 IO 操作:
scrapeZips :: [Zip] -> IO [ZipResult]
scrapeZips zipCodes = traverse scrapeZip zipCodes
但是您想添加延迟,可以使用threadDelay
(您可以从 导入它Control.Concurrent
)来完成:
scrapeZipDelay :: Zip -> IO ZipResult
scrapeZipDelay zip = do
x <- scrapeZip zip
threadDelay 1000000 -- one second in microseconds
return x
然后你可以使用scrapeZipDelay
它traverse
:
scrapeZipsDelay :: [Zip] -> IO [ZipResult]
scrapeZipsDelay zipCodes = traverse scrapeZipDelay zipCodes
除了定义一个全新的scrapeZipDelay
函数,您还可以使用<*
运算符编写一个非常小的版本:
scrapeZipsDelay :: [Zip] -> IO [ZipResult]
scrapeZipsDelay zipCodes =
traverse (\zip -> scrapeZip zip <* threadDelay 1000000) zipCodes
推荐阅读
- javascript - IPFS 应用程序中超出了最大调用堆栈。当 IPFS API 调用连续两次时
- javascript - 歌曲和弦歌词格式预览不起作用
- windows - 通过代理从个人计算机访问公共 PostgreSQL 服务器 (Amazon RDS)
- azure - 获取 azure 磁盘信息 csv
- plotly - Plotly:渲染 3D 网格椭圆体时的视觉伪影
- reactjs - 在 React 中提交表单后如何显示消息?
- java - Java - 在本机查询中设置 currentDate 时间?
- vue.js - 如何在 vue-cli 项目上没有任何新库和配置的情况下将 png 文件导入为 base64 字符串?
- c++ - 为什么 C++ 中 size_t 和 unsigned int 的混合模除会出错
- docker - 复制 docker 卷