跳转至

编写资源提供器

开始之前

Kubespider为了适配各种资源网站,抽象了一套API接口,按照Kubespider定义的规则实现这些API接口,即可实现多种方式的特定资源下载。

接口描述

对于一个资源网站的资源提供器,需要实现如下接口:

class SourceProvider(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def __init__(self) -> None:
        pass

    @abc.abstractmethod
    def get_provider_name(self):
        pass 

    @abc.abstractmethod
    def get_provider_type(self):
        pass

    @abc.abstractmethod
    def get_file_type(self):
        pass

    @abc.abstractmethod
    def get_download_path(self):
        pass

    @abc.abstractmethod
    def provider_enabled(self):
        pass

    @abc.abstractmethod
    def is_webhook_enable(self):
        pass

    @abc.abstractmethod
    def should_handle(self, dataSourceUrl):
        pass

    @abc.abstractmethod
    def get_links(self, dataSourceUrl):
        pass

    @abc.abstractmethod
    def update_config(self, reqPara):
        pass

    @abc.abstractmethod
    def load_config(self):
        pass
  • __init__: 资源提供器初始化函数,初始化一些必要状态。
  • get_provider_name: 获取资源提供器名称。
  • get_provider_type: 获取资源提供器类型,只能为SOURCE_PROVIDER_PERIOD_TYPE或者SOURCE_PROVIDER_DISPOSABLE_TYPE, 分别表示周期性资源提供器和一次性资源提供器,周期提供器可用于追剧等下载操作,一次性提供器用于webhook触发等下载操作。
  • get_file_type: 获取资源提供器下载的文件类型,可为magnet, torrent获取其他通用类型。
  • get_download_path: 获取资源提供器下载的文件存放路径,一般是每个提供一一个目录。
  • provider_enabled: 获取资源提供器是否启用,从配置文件中获取。
  • is_webhook_enable: webhook是否启用,在provider type为SOURCE_PROVIDER_DISPOSABLE_TYPE时,此接口必需返回true。
  • should_handle: 判断是否需要处理当前url,如果需要处理,返回true,否则返回false,在provider type为* SOURCE_PROVIDER_DISPOSABLE_TYPE时,此接口必需检查资源是否由此provider处理。
  • get_links: 获取此链接下的所有资源下载链接,如给一个博主地址,获取所有适配下载地址。
  • update_config: 更新资源提供器配置信息,在webhook ebable时,此接口可用于更新配置文件,如接受美剧地址,刷写地址到配置文件,然后周期下载更新剧集。
  • load_config: 获取资源提供器配置信息。

在实现如上函数后,还需要在kubespider/core/config_handler.py中初始化对应provider,如下:

source_providers = [
    mikanani_source_provider.MikananiSourceProvider(),
    btbtt12_disposable_source_provider.Btbtt12DisposableSourceProvider(),
    meijutt_source_provider.MeijuttSourceProvider(),
]

示例

这里以meijutt作为示例,实现一个资源提供器。meijutt资源提供器旨在接收webhook触发(接收喜欢的美剧地址URL),实现自动追剧。

1.配置定义

[meijutt_source_provider]
ENABLE=true
DOWNLOAD_PATH=meijutt
TV_LINKS=

这里包含3个配置属性: * ENABLE: 资源提供器是否启用,true表示启用,false表示禁用。 * DOWNLOAD_PATH: 资源提供器下载的文件存放路径,一般是每个提供一一个目录。 * TV_LINKS: 美剧地址,多个地址用逗号分隔,在收到美剧地址URL时,会通过函数update_config追加URL。

2.函数解释

class MeijuttSourceProvider(provider.SourceProvider):
    def __init__(self) -> None:
        self.provider_type = types.SOURCE_PROVIDER_PERIOD_TYPE
        self.file_type = 'magnet'
        self.webhook_enable = True
        self.provider_name = 'meijutt_source_provider'
        self.download_path = ''
        self.tv_links = []

    def get_provider_name(self):
        return self.provider_name

    def get_provider_type(self):
        return self.provider_type

    def get_file_type(self):
        return self.file_type

    def get_download_path(self):
        return self.download_path

    def provider_enabled(self):
        cfg = provider.load_source_provide_config(self.provider_name)
        return cfg['ENABLE'] == 'true'

    def is_webhook_enable(self):
        return True

    def should_handle(self, data_source_url: str):
        parse_url = urlparse(data_source_url)
        if parse_url.hostname == 'www.meijutt.tv' and 'content' in parse_url.path:
            logging.info('%s belongs to MeijuttSourceProvider', data_source_url)
            return True
        return False

    def get_links(self, data_source_url: str):
        ret = []
        for tv_link in self.tv_links:
            if len(tv_link) == 0:
                continue
            try:
                req = requests.get(tv_link, timeout=30)
            except Exception as err:
                logging.info('meijutt_source_provider get links error:%s', err)
                continue
            dom = BeautifulSoup(req.content, 'html.parser')
            div = dom.find_all("div", ['class', 'tabs-list current-tab'])
            if len(div) == 0:
                continue
            links = div[0].find_all('input', ['class', 'down_url'])
            for link in links:
                url = link.get('value')
                logging.info('meijutt find %s', url)
                ret.append(url)
        return ret

    def update_config(self, req_para: str):
        cfg = provider.load_source_provide_config(self.provider_name)
        links = cfg['TV_LINKS']
        links = str.split(links, ',')
        if req_para not in links:
            links.append(req_para)
        links = ','.join(links)
        cfg['TV_LINKS'] = links
        provider.save_source_provider_config(self.provider_name, cfg)

    def load_config(self):
        cfg = provider.load_source_provide_config(self.provider_name)
        logging.info('meijutt tv link is:%s', cfg['TV_LINKS'])
        self.tv_links = str.split(cfg['TV_LINKS'], ',')
        self.download_path = cfg['DOWNLOAD_PATH']
  • __init__: 初始化函数,包含provider类型,文件类型,是否支持webhook,资源提供器名称,下载路径,美剧地址。注意:
  • 文件类型目前只支持magnet,torrent,general。
  • meijutt资源提供器接受webhook触发,所以webhook_enable设置为true。
  • meijutt资源提供器会周期检查美剧是否更新,所以provider类型为SOURCE_PROVIDER_PERIOD_TYPE
  • 其中provider name必需合配置文件中的provider name一致。
  • get_provider_name: 直接返回此provider的name即可。
  • get_provider_type: 此provider为周期下载类型,所以返回SOURCE_PROVIDER_PERIOD_TYPE
  • get_file_type: 返回此provider的下载文件类型。
  • get_download_path: 返回下载文件夹地址。
  • provider_enabled: 读取配置文件,返回此provider是否开启。
  • is_webhook_enable: 此provider需要接收webhook触发,所以返回true。
  • should_handle: 判断请求的url是否为www.meijutt.tv,如果是则调用此provider处理。
  • get_links: 获取所有文件的下载链接。
  • update_config: 在webhook开启情况下,如果请求的url通过should_handle检查,则会调用此函数把美剧地址存如provider config文件。
  • load_config: 读取配置文件函数。

最后,在kubespider/core/config_handler.py中初始化meijutt provider,如下:

source_providers = [
    mikanani_source_provider.MikananiSourceProvider(),
    btbtt12_disposable_source_provider.Btbtt12DisposableSourceProvider(),
    meijutt_source_provider.MeijuttSourceProvider(),
]

测试

在代码写好后,直接运行如下命令打包镜像并运行即可(在此repo的根目录运行):

docker build -t cesign/kubespider:latest -f Dockerfile ./

docker rm kubespider --force

docker run -itd --name kubespider \
    -v ${HOME}/kubespider/.config:/app/.config \
    --network=host \
    --restart unless-stopped \
    cesign/kubespider:latest

然后执行你期待的操作,检查是否如期运行。