豆瓣图片防盗链怎么破解
豆瓣的豆瓣图片服务器会检查 HTTP 请求头里的 Referer 字段。如果这个字段不是图片来自 *.douban.com 域名,服务器就直接返回 403。防盗这不是链破什么高深技术,就是豆瓣一道很基础的防盗链机制。我第一次碰到这个问题是图片在写一个读书笔记聚合工具的时候,抓取豆瓣书评里的防盗配图,浏览器里看得到,链破放到自己页面上全裂了。豆瓣
浏览器打开 F12,图片切到 Network 面板,防盗刷新页面,链破找到那张图片的豆瓣请求。看 Request Headers 部分,图片Referer 那一行写的防盗是当前页面地址。豆瓣服务器就是靠这个来判断“你是不是从我们站内加载的图片”。
最直接的绕法:把 Referer 设成空或者设成豆瓣自己的域名。用 curl 试一下就知道:
curl -I -H "Referer: https://www.douban.com/" "https://img1.doubanio.com/view/subject/l/public/s1234567.jpg" 返回 200,图片正常。不加这个头,返回 403。就这么简单。
前端页面里想直接显示豆瓣图片,有个老办法是在 <head> 里加一行:
<meta name="referrer" content="no-referrer"> 这会让浏览器在发请求时不带 Referer 头。豆瓣服务器收到一个没有 Referer 的请求,有时候会放行。但这个方法不是百分百管用,豆瓣后来也改过策略,有些图片即使没有 Referer 也照样 403。而且这个 meta 标签是全局生效的,会影响页面上所有外部请求的 Referer,可能把别的服务搞挂。
更稳的做法是走服务端代理。自己的后端去请求豆瓣图片,带上伪造的 Referer,拿到二进制流之后再吐给前端。Node.js 写起来大概长这样:
app.get('/proxy/image', async (req, res) => { const imgUrl = req.query.url; const response = await fetch(imgUrl, { headers: { 'Referer': 'https://www.douban.com/' } }); res.set('Content-Type', response.headers.get('content-type')); response.body.pipe(res); }); 前端把 src 指向自己的代理接口就行。这个方案的好处是完全可控,坏处是流量走你自己的服务器,图片多了带宽扛不住。适合小规模使用。
还有一种取巧的路子:用第三方图床或者图片代理服务中转。比如 WordPress 的 Jetpack 图片 CDN(i0.wp.com),把豆瓣图片 URL 拼在它后面,让它去抓。原理一样,Jetpack 的服务器发请求时不带豆瓣的 Referer,所以能拿到图。但这类服务随时可能挂掉或者限流,不适合正经项目。
浏览器扩展是另一个场景。写 Chrome 扩展的时候,可以在 declarativeNetRequest 里改请求头,把豆瓣图片请求的 Referer 替换掉。这个权限比网页里大得多,效果也稳定。我之前写过一个豆瓣相册批量下载的扩展,就是靠这个办法拿到的原图。
豆瓣的图片域名换过好几轮,从最早的 img3.douban.com 到后来的 img1.doubanio.com,再到 img9.doubanio.com。不同域名之间的防盗策略略有差异,有的松有的紧。实际测试下来,doubanio.com 系列对空 Referer 的容忍度比老域名低一些。
说到底,Referer 防盗链本身就是个弱防护。它依赖浏览器自觉发送正确的头信息,而任何能控制 HTTP 请求的工具都能轻易伪造或去掉这个字段。豆瓣不可能不知道这一点,它只是用最低成本挡住绝大多数普通用户的直接外链,至于稍微懂点技术的人,拦不住也懒得拦。
(责任编辑:百科)













