更新calibre-web豆瓣插件calibre-web-douban-api

最近豆瓣更新了反爬政策,连封面图片也不允许直接访问,越来越严格了,以前的calibre-web-douban-api插件不能正常获取封面,因此只能想其他办法来实现封面的获取。

插件已更新到最新,本文是记录插件获取封面的技术实现,使用参考:https://fugary.com/?p=238

源码地址:https://github.com/fugary/calibre-web-douban-api/blob/main/src/NewDouban.py

如何实现

其实获取封面只需要指定Refer=https://book.douban.com头信息就可以了。

calibre-web是第三方开源服务,在不能修改其源码的情况下,要实现豆瓣封面需要处理两个问题:

  1. 封面的预览
  2. 封面下载

封面预览

封面预览实际是从浏览器根据豆瓣的封面url直接发起请求,没有办法增加头信息(Chrome浏览器插件倒是可以实现),因此只能通过本地服务代理访问豆瓣url

代理地址

calibre-web是用flask开发,可以考虑引入flask的蓝图对象,自己添加一个路由地址,在路由中转发请求,参考代码:

from cps.search_metadata import meta
from flask import request, Response

@meta.route("/metadata/douban_cover", methods=["GET"])
def proxy_douban_cover():
    cover_url = urllib.parse.unquote(request.args.get('cover'))
    res = requests.get(cover_url, headers=DEFAULT_HEADERS)
    return Response(res.content, mimetype=res.headers['Content-Type'])

这样就实现了,通过本地的/metadata/douban_cover?cover=https://xxxx地址显示封面了。

服务地址

有了本地代理服务,然后就需要在返回封面数据的时候把这个代理服务替换原始的豆瓣封面地址。

这里有点麻烦,因为flaskrequest对象是通过线程本地变量实现,元数据服务又是通过线程池去获取元数据,线程池中是获取不到request对象的,尝试获取将会报错。

{RuntimeError}RuntimeError('Working outside of request context.nnThis typically means that you attempted to use functionality that needednan active HTTP request. Consult the documentation on testing forninformation about how to avoid this problem.')

因此只有在元数据获取之后、往外输出之前来修改封面地址,这里通过继承MetaRecord重写魔法函数__getattribute__来实现封面url地址的替换,参考代码:

@dataclasses.dataclass
class DoubanMetaRecord(MetaRecord):

    def __getattribute__(self, item):  # cover通过本地服务代理访问
        if item == 'cover' and DOUBAN_PROXY_COVER:
            cover_url = super().__getattribute__(item)
            if cover_url:
                try:
                    host_url = DOUBAN_PROXY_COVER_HOST_URL
                    if not host_url and request.host_url:
                        host_url = request.host_url
                    if host_url and host_url not in cover_url:
                        self.cover = host_url + DOUBAN_PROXY_COVER_PATH + urllib.parse.quote(cover_url)
                except BaseException:
                    pass
        return super().__getattribute__(item)

这样就实现了豆瓣封面预览功能了。

如果获取的服务器地址不正确,可以手动指定DOUBAN_PROXY_COVER_HOST_URL='http://nas_ip:8083/'

封面下载

这个本地代理地址不能实现封面下载,因为如果在保存封面的flask路由中再次访问其他flask路由会卡死,感觉是因为没有开启flask的多线程处理请求的原因,在不修改calibre-web的情况下,要实现封面下载,可以覆盖calibre-webhelper.save_cover_from_url方法,用自己写的方法去替换掉save_cover_from_url,在检测到是douban的封面地址的情况下,用requests去下载封面数据,代码如下:

    @staticmethod
    def hack_helper_cover():
        save_cover = helper.save_cover_from_url
        def new_save_cover(url, book_path):
            if DOUBAN_COVER_DOMAIN in url:
                cover_url = url
                if DOUBAN_PROXY_COVER:
                    component = urllib.parse.urlparse(url)
                    query = urllib.parse.parse_qs(component.query)
                    cover_url = urllib.parse.unquote(query.get('cover')[0])
                res = requests.get(cover_url, headers=DEFAULT_HEADERS)
                return helper.save_cover(res, book_path)
            else:
                return save_cover(url, book_path)
        helper.save_cover_from_url = new_save_cover

这样就实现了封面预览和下载了。

更新calibre-web豆瓣插件calibre-web-douban-api

给TA打赏
共{{data.count}}人
人已打赏
运维

群晖NAS安装JupyterLab基本使用

2024-11-19 10:38:43

运维

JavaFX简单计算器Demo并打包成安装包

2024-11-19 10:38:47

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索