跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Golang如何做网页爬虫_Golang爬虫开发教程【技巧】

必须手写*http.Client:设10秒超时、连接池、UA头、禁自动跳转;HTML解析用goquery而非正则;并发用信号量限流;URL去重+深度控制保命;响应体及时关闭并处理中文编码。 别用
http.Get
,必须手写
*http.Client
直接调
http.Get
看似省事,但上线两小时就挂——不是代码错,是默认客户端没超时、没连接池、没 UA,目标站一拦一个准,本地还容易耗尽文件描述符。 显式构造
*http.Client
,至少设
Timeout: 10 * time.Second
加
Transport
控制连接复用:
MaxIdleConns: 100
和
MaxIdleConnsPerHost: 100
是安全起点
User-Agent
必须设,值用常见浏览器字符串,比如
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
,别留空或用 Go 默认标识 遇到跳转页被重定向吃掉原始响应(比如 302 后返回登录页),要禁自动跳转:
CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }
解析 HTML 别碰正则,
goquery
是底线选择 用
regexp
提取
</code></div> 或链接?页面多一个空格、换一行、属性顺序一变,就全失效。这不是写得不够巧,是根本不在同一抽象层上。 用 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">github.com/PuerkitoBio/goquery</code></div> ,它底层调的是 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">golang.org/x/net/html</code></div> ,能处理真实 DOM 结构 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">s.Text()</code></div> 比 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">s.Nodes[0].FirstChild.Data</code></div> 安全得多——前者自动合并文本节点、清理空白,后者一碰到注释或 CDATA 就 panic <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">s.Attr("href")</code></div> 返回 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">(string, bool)</code></div> ,务必检查第二个值;别用 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">s.Get(0).Attr</code></div> ,属性不存在时直接崩溃 相对 URL 要转绝对地址: <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">url.Join(baseURL, href)</code></div> ,否则存下来全是 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">/post/123</code></div> 这种无效链接 并发不是开越多越快, <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">sem := make(chan struct{}, N)</code></div> 才管用 起 100 个 goroutine 直接 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">c.Visit()</code></div> ,看着快,实则三秒后卡死:DNS 查询阻塞、TCP 端口占满、目标站返回 429、本地 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">too many open files</code></div> 全来了。 用带缓冲的 channel 当信号量: <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">sem := make(chan struct{}, 4)</code></div> ,每次发请求前 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">sem <- struct{}{}</code></div> ,结束后 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto"><-sem</code></div> 别用 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">time.Sleep</code></div> 模拟人工节奏——它不防并发突增;真要限频,用 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">golang.org/x/time/rate.Limiter</code></div> 对同一域名做请求间隔,可用 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">sync.Map</code></div> 记录上次时间,配合 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">time.Since</code></div> 判断是否可发 Colly 用户注意: <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">c.Async = true</code></div> 只是开关,并发数由 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">c.Limit(&colly.LimitRule{Parallelism: 4})</code></div> 控制,不设就是串行 去重和深度控制不是可选项,是保命线 没 URL 去重?爬虫三分钟内就会在两个页面之间反复横跳;不限制深度?从首页开始, <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">a[href]</code></div> 一递归,几万链接瞬间进队列,内存爆掉只是时间问题。 立即学习 “ go语言免费学习笔记(深入) ”; 去重 key 必须标准化: <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">strings.ToLower(u.Scheme + "://" + u.Host + u.EscapedPath())</code></div> ,去掉 fragment,统一大小写 用 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">map[string]struct{}</code></div> 内存去重最快;如果需跨进程或持久化,再考虑 Redis 或 Bloom Filter <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">-depth</code></div> 参数建议默认为 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">2</code></div> ,设为 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">0</code></div> 表示只抓当前页;Colly 用户记得配 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">c.MaxDepth = 2</code></div> 发现新链接时,先查重再入队,BFS 模式比 DFS 更可控 最常被忽略的不是怎么写,而是怎么收尾:所有 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">resp.Body</code></div> 必须 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">defer resp.Body.Close()</code></div> ,所有 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">goquery.Document</code></div> 不用关,但它的源 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">io.Reader</code></div> 如果是文件或自定义流,就得你来关。还有,中文乱码不是编码错了,是没用 <div class="cxy-code-block"><button class="cxy-code-copy" aria-label="复制代码">复制</button><code class="language-auto">charset.NewReaderLabel</code></div> 套一层响应体。 </div> <!-- 文章导航 --> <nav class="xjpbg-article-nav" aria-label="文章导航"> <a href="http://www.xjpbg.com/bg/38604.html" class="xjpbg-article-nav-link xjpbg-article-nav-prev"> <span>‹</span> <div> <div class="xjpbg-article-nav-label">上一篇</div> <div class="xjpbg-article-nav-title">php作wap开发时遇到的问题_PHP教程</div> </div> </a> <a href="http://www.xjpbg.com/bg/38617.html" class="xjpbg-article-nav-link xjpbg-article-nav-next"> <div> <div class="xjpbg-article-nav-label">下一篇</div> <div class="xjpbg-article-nav-title">Gate.io交易所入口:官方App下载指南</div> </div> <span>›</span> </a> </nav> </div> </article> <!-- 相关文章列表 --> <section class="xjpbg-content-section" style="margin-top: 20px;"> <h2 class="xjpbg-widget-title" style="margin-bottom: 20px;">相关文章</h2> <ul class="xjpbg-article-list"> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38604.html" class="xjpbg-article-link">php作wap开发时遇到的问题_PHP教程</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38591.html" class="xjpbg-article-link">PHP PDO 命名占位符使用规范与 SQLSTATE[HY093] 错误解决</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38570.html" class="xjpbg-article-link">Adobe Dreamweaver CS5 官方中文版安装步骤图文示例</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38541.html" class="xjpbg-article-link">php网站模板怎么修改_修改php网站模板文件教程【模板】</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38538.html" class="xjpbg-article-link">Golang开发:使用Websocket实现实时聊天应用</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38617.html" class="xjpbg-article-link">Gate.io交易所入口:官方App下载指南</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38620.html" class="xjpbg-article-link">python实现发送和获取手机短信验证码</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38621.html" class="xjpbg-article-link">php数组去除空值函数分享_PHP</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38623.html" class="xjpbg-article-link">php中作用域操作符支持链式调用吗_静态方法链式操作实现【介绍】</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38624.html" class="xjpbg-article-link">运行python需要什么显卡</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> </ul> </section> </div> <!-- 右侧边栏 --> <aside class="xjpbg-sidebar xjpbg-sidebar-right" aria-label="侧边栏"> <!-- 推荐阅读 --> <div class="xjpbg-widget"> <h3 class="xjpbg-widget-title">推荐阅读</h3> <div class="xjpbg-recommend-grid"> <a href="http://www.xjpbg.com/bg/38628.html" class="xjpbg-recommend-item"> <div class="xjpbg-recommend-thumb"> <img src="http://www.xjpbg.com/static/v6/images/article-6.jpg" alt="如何基于分组将词表列表展开并追加为 DataFrame 新行"> </div> <div class="xjpbg-recommend-title">如何基于分组将词表列表展开并追加为 DataFrame 新行</div> </a> <a href="http://www.xjpbg.com/bg/38624.html" class="xjpbg-recommend-item"> <div class="xjpbg-recommend-thumb"> <img src="http://www.xjpbg.com/static/v6/images/article-6.jpg" alt="运行python需要什么显卡"> </div> <div class="xjpbg-recommend-title">运行python需要什么显卡</div> </a> <a href="http://www.xjpbg.com/bg/38623.html" class="xjpbg-recommend-item"> <div class="xjpbg-recommend-thumb"> <img src="http://www.xjpbg.com/static/v6/images/article-6.jpg" alt="php中作用域操作符支持链式调用吗_静态方法链式操作实现【介绍】"> </div> <div class="xjpbg-recommend-title">php中作用域操作符支持链式调用吗_静态方法链式操作实现【介绍】</div> </a> <a href="http://www.xjpbg.com/bg/38621.html" class="xjpbg-recommend-item"> <div class="xjpbg-recommend-thumb"> <img src="http://www.xjpbg.com/static/v6/images/article-6.jpg" alt="php数组去除空值函数分享_PHP"> </div> <div class="xjpbg-recommend-title">php数组去除空值函数分享_PHP</div> </a> </div> </div> <!-- 最新文章 --> <div class="xjpbg-widget"> <h3 class="xjpbg-widget-title">最新文章</h3> <ul class="xjpbg-article-list"> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38628.html" class="xjpbg-article-link">如何基于分组将词表列表展开并追加为 DataFrame 新行</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38624.html" class="xjpbg-article-link">运行python需要什么显卡</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38623.html" class="xjpbg-article-link">php中作用域操作符支持链式调用吗_静态方法链式操作实现【介绍】</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38621.html" class="xjpbg-article-link">php数组去除空值函数分享_PHP</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38620.html" class="xjpbg-article-link">python实现发送和获取手机短信验证码</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> <li class="xjpbg-article-item"> <a href="http://www.xjpbg.com/bg/38617.html" class="xjpbg-article-link">Gate.io交易所入口:官方App下载指南</a> <div class="xjpbg-article-meta">2026-11-08</div> </li> </ul> </div> <!-- 热门标签 --> <div class="xjpbg-widget"> <h3 class="xjpbg-widget-title">热门标签</h3> <div class="xjpbg-article-tag-list"> <a href="http://www.xjpbg.com/tag/1718" class="xjpbg-article-tag-item">golang</a> <a href="http://www.xjpbg.com/tag/1632" class="xjpbg-article-tag-item">go</a> </div> </div> </aside> </div> </div> </main> <!-- 页脚 --> <footer class="xjpbg-footer"> <div class="xjpbg-container"> <div class="xjpbg-footer-links" style="justify-content: center;"> <a href="http://www.xjpbg.com/22.html" class="xjpbg-footer-link">免责声明</a> <a href="http://www.xjpbg.com/23.html" class="xjpbg-footer-link">关于我们</a> <a href="http://www.xjpbg.com/24.html" class="xjpbg-footer-link">联系我们</a> <a href="http://www.xjpbg.com/25.html" class="xjpbg-footer-link">投诉删除</a> <a href="http://www.xjpbg.com/26.html" class="xjpbg-footer-link">投稿须知</a> </div> <div class="xjpbg-footer-copyright" style="text-align: center; margin-top: 20px;"> Copyright 2026 新派编程网 版权所有 <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank" style="color: inherit;">黔ICP备2025064387号</a> </div> <div style="text-align: center; margin-top: 10px; font-size: 12px; color: #999;">免责声明:本站信息来源于网络,仅供学习使用,版权归原作者所有,如有不愿意被转载的情况,请联系QQ:182111886,通知我们删除已转载的信息。</div> </div> </footer> <!-- 返回顶部按钮 --> <button class="xjpbg-back-to-top" id="backToTop" aria-label="返回顶部">⇧</button> <!-- 公共脚本 --> <script src="http://www.xjpbg.com/static/v6/js/common.js"></script> <div class="hide"> </div> </body> </html>