Unsplash国内镜像接口实现
故事背景:网站一直使用的是Unsplash的随机图床API,由于unsplash在国内属于半墙状态,所以有很多墙内小伙伴反映页面加载很慢。博主试图找一些国内图床接口用来取代unsplash,可惜都不太符合审美(点赞unsplash图片质量),无意间发现了一个unsplash国内镜像站:https://unsplash.dogedoge.com/,但可惜的是站长只镜像了静态文件,网站没有任何API接口可供调用。万幸的是通过对比发现镜像图片id和原unsplash网站一致,也就是只需要替换图片前缀就能得到国内镜像链接,于是准备自己动手做一个中间件用来实现镜像站的随机图片接口功能。
接口需求分析
需要接收图片长宽、图片标签等参数
将参数传递给unsplash官方接口获取随机图片链接,简称原始链接
通过拼接替换url,获取国内镜像图片链接,简称最终链接
将请求重定向到最终链接,获取图片
接口实现
由于source.unsplash接口已作废,所以以下部分已失效,仅做存档使用,请知悉!!!
获取Unsplash原始链接
观察unsplash官方接口:https://source.unsplash.com/random/900×700/?blog,night,sea
其中900x700分别代表图片宽高,blog,night,sea代表图片标签,也就是随机哪些类型的图片当我们发送请求时,接口会返回一个携带302响应,把我们重定向到真实的图片链接,Headers中的location就是我们要获取的图片链接了
通过代码简单实现如下:
import requests url = "https://source.unsplash.com/random/900×700/?blog" # 这里要取消重定向,否则response会跳转到图片链接 response = requests.get(url,allow_redirects=False) print(response.headers.get("Location"))
返回示例:
https://images.unsplash.com/photo-1499750310107-5fef28a66643?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxfDB8MXxyYW5kb218MHx8YmxvZ3x8fHx8fDE2OTgxNDE1Mjg&ixlib=rb-4.0.3&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1080
拼接国内镜像最终链接
这一步就比较简单了,直接替换原始链接中的
https://images.unsplash.com/
部分即可代码如下:
import requests from urllib.parse import urljoin url = "https://source.unsplash.com/random/900×700/?blog" try: response = requests.get(url, allow_redirects=False) location = response.headers.get("Location") if location: final_url = urljoin("https://dogefs.s3.ladydaily.com/~/source/unsplash/", location.replace("https://images.unsplash.com/", "")) print(final_url) else: print("Location header not found in the response.") except requests.RequestException as e: print(f"Request failed: {e}")
返回示例:
https://dogefs.s3.ladydaily.com/~/source/unsplash/photo-1531346878377-a5be20888e57?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxfDB8MXxyYW5kb218MHx8YmxvZ3x8fHx8fDE2OTgxNDE0ODA&ixlib=rb-4.0.3&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1080
打开示例链接,图片可以正常访问,且国内访问速度正常。
web框架代码(已作废)
上面我们使用脚本实现了最终链接的获取,但我们最终是要通过API接口供网站调用,所以需要将脚本搬到web框架中,由于博主的服务器内存告急,因此这里采用了羽量级的web.py框架,另外还有flask、django等框架也可实现
最终代码如下:
import web import requests from urllib.parse import urljoin urls = ( '/get_image', 'get_image' ) app = web.application(urls, globals()) class get_image: def GET(self): # 接收宽高、tag参数 width = web.input().get('width', '100') height = web.input().get('height', '100') tags = web.input().get('tags', '') # 构建带参数的原始链接 url = f"https://source.unsplash.com/random/{width}x{height}/?{tags}" try: response = requests.get(url, allow_redirects=False) location = response.headers.get("Location") if location: final_url = urljoin("https://dogefs.s3.ladydaily.com/~/source/unsplash/", location.replace("https://images.unsplash.com/", "")) raise web.seeother(final_url) # 使用web.seeother进行重定向 else: return "Location header not found in the response." except requests.RequestException as e: return f"Request failed: {e}" if __name__ == "__main__": app.run()
web服务代码
修改思路:通过unsplash开发者平台调用随机接口,需要先注册开发者,创建APP后拿到自己的Access_Key,代码变更如下:
import web
import requests
from urllib.parse import urljoin
urls = (
'/get_image', 'get_image'
)
app = web.application(urls, globals())
class get_image:
def GET(self):
width = web.input().get('width', '100')
height = web.input().get('height', '100')
tags = web.input().get('tags', '') # 获取标签参数
client_id = "替换为自己的Access_Key"
url = "https://api.unsplash.com/photos/random"
params = {
'client_id': client_id,
'query': tags,
'w': width,
'h': height
}
try:
response = requests.get(url, params=params)
response.raise_for_status() # 检查请求是否成功
data = response.json()
image_url = data['urls']['regular']
# 将最终图片地址替换为https://dogefs.s3.ladydaily.com/
modified_url = urljoin("https://dogefs.s3.ladydaily.com/~/source/unsplash/", image_url.split("/")[-1])
raise web.seeother(modified_url) # 使用web.seeother进行重定向
except requests.RequestException as e:
return f"Request failed: {e}"
except KeyError:
return "Error: Unable to fetch the image URL from the response."
if __name__ == "__main__":
app.run()
接口服务部署
在服务器中安装依赖
pip install web.py pip install requests
启动接口服务
nohup python3 app.py 8888 >/dev/null 2>&1 &
nginx反向代理
location /unsplash { proxy_pass http://localhost:8888/get_image; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }
最终效果
请求格式
https://blog.newmorning.work/unsplash?width=900&height=700&tags=blog,night,blue
返回
https://dogefs.s3.ladydaily.com/~/source/unsplash/photo-1620590532278-c9225fc3eac6?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=700&ixid=MnwxfDB8MXxyYW5kb218MHx8YmxvZyxuaWdodCxibHVlfHx8fHx8MTY5ODE0MjYwNw&ixlib=rb-4.0.3&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=900