0

0

如何使用Golang实现并发网络爬虫_Golang goroutine与HTTP请求技巧

P粉602998670

P粉602998670

发布时间:2026-01-21 11:24:58

|

819人浏览过

|

来源于php中文网

原创

Go并发爬虫关键在于控并发、防崩、防封;需用带缓冲channel实现信号量限流,归一化URL并用sync.Map去重,限制响应体大小并确保resp.Body.Close()。

如何使用golang实现并发网络爬虫_golang goroutine与http请求技巧

Go 语言实现并发爬虫的关键不在“能不能并发”,而在于“怎么控并发、怎么防崩、怎么不被封”。盲目开成百上千个 goroutinehttp.Get,大概率触发连接耗尽、DNS 超时、服务端限流或本地文件描述符不足(too many open files)。

semaphore 控制并发请求数量

别靠 time.Sleep 或空 for 循环压节奏。标准做法是用带缓冲的 channel 模拟信号量,限制同时活跃的 HTTP 请求数量。

常见错误:直接对每个 URL 启一个 go fetch(url),没节制 —— 1000 个 URL 就起 1000 个 goroutine,底层 TCP 连接、DNS 查询、TLS 握手全堆在一起,系统先扛不住。

  • 设一个 sem := make(chan struct{}, 10),表示最多 10 个并发请求
  • 每次发请求前写入:sem
  • 请求结束(无论成功失败)后必须释放:
  • 这个 channel 不要 close,也不用 defer —— 它是长期复用的资源

http.Client 必须复用并配置超时

每个 http.Client 实例自带连接池;反复 new http.Client 会导致连接泄漏、TIME_WAIT 爆满、DNS 缓存失效。

立即学习go语言免费学习笔记(深入)”;

默认的 http.DefaultClient 虽可用,但超时为 0(无限等待),极易卡死整个 goroutine。

虎课网
虎课网

虎课网是超过1800万用户信赖的自学平台,拥有海量设计、绘画、摄影、办公软件、职业技能等优质的高清教程视频,用户可以根据行业和兴趣爱好,自主选择学习内容,每天免费学习一个...

下载
  • 定义全局或包级变量:var client = &http.Client{Timeout: 10 * time.Second}
  • 设置 Transport 复用连接:
    client.Transport = &http.Transport{
        MaxIdleConns:        100,
        MaxIdleConnsPerHost: 100,
        IdleConnTimeout:     30 * time.Second,
    }
  • 不要在 handler 或循环里反复 new http.Client,哪怕只改 Timeout

解析 HTML 前先检查 resp.StatusCodeContent-Type

很多爬虫一拿到 *http.Response 就直接丢给 golang.org/x/net/html 解析,结果遇到 404 页面、JSON 接口、重定向响应、二进制文件(PDF/图片),轻则 panic(invalid character),重则静默跳过关键错误。

  • 务必检查:if resp.StatusCode = 300
  • 检查 Content-Type 是否含 text/htmlapplication/xhtml+xml,否则跳过解析
  • io.LimitReader(resp.Body, 1024*1024) 防止下载超大响应体(如视频页面嵌了 100MB 日志文件)
  • 记得 resp.Body.Close() —— 不关会泄漏连接,尤其在复用 client 时

URL 去重与避免重复抓取要用 sync.Map + 归一化

原始 URL 可能带不同 query 参数(?utm_source=xx)、大小写路径、末尾斜杠差异,直接字符串比较会导致重复抓取或漏抓。

并发环境下用普通 map[string]bool 会 panic,必须线程安全。

  • var visited = sync.Map{} 存已抓 URL(key 是归一化后的字符串)
  • 归一化至少做三件事:转小写、移除 fragment(# 后内容)、标准化 query(按 key 排序再拼)
  • 判断是否已访问:if _, ok := visited.Load(normalizedURL); ok { continue }
  • 成功解析后存入:visited.Store(normalizedURL, struct{}{})

真正难的不是并发本身,而是当 50 个 goroutine 同时在解析、去重、写磁盘、重试 429 响应时,哪条路径没加锁、哪个 error 被忽略、哪个 body 忘了 close —— 这些细节才决定爬虫跑一天后是稳如磐石,还是凌晨三点开始疯狂报 dial tcp: lookup xxx: no such host

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

180

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

228

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

340

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

209

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

393

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

197

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

191

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

212

2025.06.17

Java编译相关教程合集
Java编译相关教程合集

本专题整合了Java编译相关教程,阅读专题下面的文章了解更多详细内容。

9

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.9万人学习

AngularJS教程
AngularJS教程

共24课时 | 2.8万人学习

CSS教程
CSS教程

共754课时 | 21.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号