URLConnection 不推荐用于新爬虫项目——它缺乏重试、连接池、自动解压,需手动处理 gzip 解压、301/302/307/308 重定向、超时、编码、异常及资源关闭,健壮性与可维护性远低于 OkHttp 等现代库。

URLConnection 能抓网页源码,但不推荐在新项目里用它做爬虫——它没重试、没连接池、没自动解压,连 302 重定向都要手动处理。
URLConnection 默认不支持 gzip 压缩,返回乱码或空内容
很多网站(尤其是现代 CDN)默认开启 gzip 响应压缩。而 URLConnection 不会自动解压,你拿到的可能是二进制压缩流,直接转字符串就是乱码或空。
- 必须显式设置请求头:
connection.setRequestProperty("Accept-Encoding", "gzip") - 读取前判断响应头:
connection.getContentEncoding()是否为"gzip" - 是 gzip 就用
GZIPInputStream包装connection.getInputStream(),再用InputStreamReader指定编码(如"UTF-8") - 别依赖
connection.getContentEncoding()的返回值——有些服务器不返回该 header,但实际仍压缩了;更稳妥的做法是检查connection.getHeaderField("Content-Encoding")
重定向(301/302)不会自动跳转,需手动处理
URLConnection 默认关闭自动重定向(setInstanceFollowRedirects(false)),哪怕你设成 true,它也只处理 302,且不透传原始请求方法(比如 POST 重定向后变成 GET)。
- 建议设
connection.setInstanceFollowRedirects(false),自己控制逻辑 - 检查响应码:
connection.getResponseCode()是否为301、302、307、308 - 从
connection.getHeaderField("Location")取跳转地址,构造新URL并递归请求(注意限制跳转次数,防环) - 对
307和308,要保持原请求方法和 body;301/302通常视为 GET 语义,丢弃 body
超时、异常、字符编码必须显式设置,否则极易卡死或出错
不设超时,connect() 或 getInputStream() 可能无限阻塞;不指定编码,InputStreamReader 用平台默认编码(Windows 是 GBK),中文网站大概率乱码。
- 必须设三类超时:
connection.setConnectTimeout(5000)、connection.setReadTimeout(5000)、connection.setInstanceFollowRedirects(false)(避免 redirect 期间无 timeout) - 字符编码优先从响应头获取:
connection.getContentType()解析charset=, fallback 到"UTF-8" - 捕获常见异常:
IOException(网络断、超时)、UnknownHostException(域名解析失败)、SSLHandshakeException(HTTPS 证书问题) - 记得关流:
InputStream和InputStreamReader都要close(),建议用 try-with-resources
真正难的不是“怎么拿到源码”,而是处理压缩、跳转、编码、证书、反爬 header、连接复用这些细节。用 URLConnection 写一个健壮的抓取器,代码量不会比用 OkHttp 少,可维护性反而更低——尤其是当你要加 cookie 管理、代理、DNS 缓存时。

















