背景:
自己一直用Rsshub+Freshrss+Reeder来获取资讯,其中包括少数派。之前用的官方的Rss,发现他只给预览部分内容了,于是换Rsshub给的feed,正常了一阵子。 好景不常,前一段时间发现少数派的图片又展示不全了,估计又在搞事了。搜了一圈,发现最大的问题可能就是加了防盗链了。
一般网站的图片的防盗链策略基本就是:主站+no-refer,但是少数派为了给自己的网站和app引流确实费劲心思了,去掉了no-refer,只允许refer是 sspai.com 了。而Rsshub抓取网站的图片默认都是no-refer.
怎么解决呢:
在往上搜了一圈之后,发现Fressrss的插件库里面有ImageProxy和ImageCache能解决这个问题,但是自用不需要缓存图片这种开销比较大的操作,所以选择了ImageProxy.
根据各种资料,在Vps上面搭建了一个反代地址,部分代码如下:
1 | map $arg_path $new_referer { |
关键点:
#1.map配置 图片链接正则匹配到sspai.com之后 新的refer就是sspai.com
#2.反代配置 如果map没匹配到需要反代的域名直接302访问原始图片链接, 如果匹配到了,就在header里面修改新的Referer,然后用的是Vps访问链接。
#3.最后在Freshrss里面配置插件,地址为Vps地址或者域名,后缀加上/proxy?path=
到这,Freshrss里面打开少数派的Feed,图片就能正常展示了。
但是。。。。。。。
一般都用手机Reeder访问Freshrss,手机上面打开的时候却不生效,这是为什么呢?结合上面说的有两个插件,一个是ImageProxy一个是ImageCache,看了ImageCache的Github里面的用户访问时序图。
发现这个插件在客户端访问的时候可以直接读取cache而不是读取Freshrss,于是对比了下两个插件的代码,发现主要的区别在于Hook.
ImageProxy插件是在展示前调用,而ImageCache是在插入Freshrss数据库之前,先将图片上传到配置的路径,然后不修改内容,但是在展示的时候,再查询缓存的地址。虽然两个插件都不能在其他App直接展示图片,但是ImageCache的entry_before_insert Hook引起我的注意。根据语义可以得知,在feed解析后,每篇文章都会插入数据库。然后查证了Freshrss的数据库,果然,entry表里面的content字段存了最原始的Rsshub返回的内容。
这也就解释了为啥其他App读取的时候,代理的图片还是不生效的问题,因为插件根本没有修改原始数据,只是在浏览器访问Freshrss的时候,Feed展示前插件才会工作。
进一步修改:
将ImageProxy插件的Hook从entry_before_display改为entry_before_insert,保存并重启Freshrss,等待下一次刷新Feed的时候,发现数据库里面的Content内容里面所有Img标签的src属性都变成了反代地址+原始图片链接。至此,所有App访问Freshrss之后都能展示图片了。
ps:这样做也有一个缺点,你的反代服务器需要一直在线,如果不能访问了,文章中所有图片也都失效了,包含不需要反代的。
Ref:
#1. https://undefapp.com/freshrss-jie-jue-sspai-tu-pian-fang-dao-lian-wen-ti
#3. https://flowus.cn/share/822c6b09-715d-47f6-8b49-d9fa3804e235