如果 A 站点想将 B 站点的 img 等资源放到 A 站点,通常会受到对方站点防盗链的阻拦。这里是我提供的一个思路,利用腾讯云函数的免费资源,完美绕开防盗链。因为图片不会受到浏览器的跨域阻拦,其他资源的跨域问题也能通过这个方法解决。

1:什么是防盗链?

防盗链是由对方站点设置的,防止未受许可的站点直接引用对方站点的资源。比如这里有一个 https://www.baidu.com/abc.jpg  图片链接,如果你想将它放到 www.yourweb.com  站点的 img 标签 src 中,将受到防盗链的阻挡,浏览器将无法加载此图片。
防盗链是因为浏览器在发起跨域请求时携带了,referrer 请求头,此请求头含有你的站点主机,对方识别到你非许可站点,因此拒绝返回给你图片资源。
我在网上找了一些解决防盗链的办法,比如,设置 meta 标签为 no-referrer,使用 iframe,反向代理等。其中,针对 B 站防盗链的 meta 标签无效,iframe 过于臃肿,不适合设置,而反向代理则需要一台服务器,价格不美丽,我直接用别人网站上的资源,不就是为了白嫖吗?
对此我找到了一个,免费破解防盗链的方法。

2:破解防盗链

我在腾讯云函数上写了一个 python 程序,此程序,将图片资源直径转为 base64 数据,然后返回给请求者。
为什么腾讯云函数?
腾讯云函数每个月有免费的额度,其中 100 万次 api 调用,40 万 GBs 的函数运行时长(1GBs 表示,内存 1GB 运行 1 秒),还有大概几个 G 的外网流出流量。这美丽的免费量,足够我们做图片代理了。
为什么转 base64?
首先,腾讯云函数不支持直接返回二进制或者图片资源,它只能返回纯字符串文本,或者 json 格式的字符串。python 可以利用 base64 库,将图片转为 base64 字节流,然后对其解码生成字符串。
除此之外,base64 格式的字符串可以直接放入 img 标签的 src 中,而无需再转为 blob。
python 代码:

1
2
3
4
5
6
7
8
9
10
11
12
import requests
import base64
from io import BytesIO
import os

#返回一个字符串,可直接放到img标签src中
#img_url图片的url
def getImgtoBase64(img_url):
resp = requests.get(img_url)
img_bytes=base64.b64encode(BytesIO(resp.content).read())
img_str = img_bytes.decode()
return 'data:image/'+os.path.basename(img_url)+';base64,'+img_str

这里只有关键代码,如何通过云函数 api 向云函数中传入 imgurl,需要额外的程序,比如 post 请求中添加 url 参数,或者 get 请求参数中放入 unicode 编码后的 url。
更多的解决办法,需要自行了解云函数。因为我的 imgurl 是直接在 python 程序中通过爬虫爬取的,没有通过前端发送 imgurl 所以没有再贴出来。这里贴出一些云函数的可能返回方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#前端请求时将url编码
#通过get请求传入imgurl参数,https://serverless-api.com/?imgurl=www.baidu.com%2fabc.jpg
def main_handler(event,context):
if('imgurl' in event['queryString']):
imgurl = event['queryString']['imgurl']
#TODO 将imgurl进行url解码
#imgurl_decoded=
img_str = getImgtoBase64(imgurl_decoded)
#返回json格式的内容
return {
"isBase64Encoded": False,
"statusCode": 200,
"headers": {'Content-Type': 'application/json','Access-Control-Allow-Origin':'*'},
"body": {'imgstr':img_str}
}

如果不是图片资源,加入Access-Control-Allow-Origin  可以解决跨域问题。

评论