使用Golang实现一个简单的网站死链检测工具 Go语言并发HTTP请求

4次阅读

使用 http.client 并发检测死链时,须设 timeout 控制请求生命周期,用 waitgroup+channel 限并发,结合状态码、响应体内容及重定向处理综合判断“死链”,并用 golang.org/x/net/html 安全提取链接。

使用Golang实现一个简单的网站死链检测工具 Go语言并发HTTP请求

http.Client 发起并发请求时,别忘了设置超时

死链检测本质是大量发 HTTP 请求,不设超时的话,一个卡住的链接会让整个 goroutine 永久阻塞,最终耗尽资源。Go 默认的 http.DefaultClient 没有超时,必须显式配置。

  • &http.Client{Timeout: 10 * time.Second} 控制单次请求上限
  • 别只设 net.DialTimeout,它只管建连;要覆盖整个请求生命周期,用 Timeout 字段
  • 如果需要更精细控制(比如分开设置连接、读、写超时),改用 Transport 配置,但对死链检测来说,Timeout 足够且不易出错

sync.WaitGroup + chan 控制并发量,不是无脑开 1000 个 goroutine

爬全站链接时,可能一次性拿到几千 URL。全丢进 goroutine 不仅容易被目标服务器限流或拉黑,还会触发系统文件描述符耗尽、DNS 查询阻塞等问题。

  • 固定 worker 数量:启动 10–50 个长期运行的 goroutine,从 channel 里取 URL 处理
  • sync.WaitGroup 等待所有任务结束,别依赖 time.Sleep 或计数器手动判断
  • channel 缓冲区大小设为待检测 URL 总数,避免发送端阻塞;接收端关闭 channel 后,worker 自动退出

判断“死链”的依据不能只看 status != 200

HTTP 状态码只是第一层信号。404 是典型死链,但 301/302 跳转目标不可达、503 临时不可用、甚至 200 但返回空页或错误 HTML,都该归为异常。

  • 必须检查 resp.StatusCode,但也要读取响应体前几十字节,确认是否真返回了有效内容(比如含 或预期关键词)
  • 对重定向,建议设 CheckRedirectfunc(req *http.Request, via []*http.Request) Error { return http.ErrUseLastResponse },自己处理跳转逻辑,避免丢失中间状态
  • 遇到 net/http: request canceledcontext deadline exceeded 这类错误,属于超时或主动取消,应单独归类,不和 4xx/5xx 混淆

解析 HTML 提取链接时,优先用 golang.org/x/net/html,别正则匹配

网页中 <a href="..."></a> 的格式千奇百怪:引号可有可无、空格位置随意、URL 可能是相对路径。正则极易漏匹配或误伤。

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

  • golang.org/x/net/html 是 Go 官方维护的健壮解析器,能正确处理嵌套、命名空间、自闭合标签等边界情况
  • 提取 href 后,用 url.Join(baseURL, href) 转成绝对地址,baseURL 是当前页面 URL,不是根域名
  • 注意过滤掉 javascript:mailto:tel: 等非 HTTP 协议链接,避免 http.Getunsupported protocol scheme

真正难的不是并发或发请求,而是怎么定义“死”——是服务器没响应?是返回了 404?还是页面结构崩了但 HTTP 状态码还是 200?这些判断逻辑得贴着业务来,没法靠工具自动猜准。

text=ZqhQzanResources