animag


Nameanimag JSON
Version 2.0.0 PyPI version JSON
download
home_pagehttps://github.com/adogecheems/animag
SummaryAnime magnet search library with strong expandability
upload_time2024-12-22 09:01:14
maintainerNone
docs_urlNone
authoradogecheems
requires_pythonNone
licenseAGPLv3
keywords anime magnet torrent scrape spider rss expandable plugin acgrip dmhy nyaa tokyotosho miobt kisssub comicat
VCS
bugtrack_url
requirements requests bs4 lxml rich
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <h1 align="center" style="font-size: 3rem; color: #1772b4">Animag 2.0</h1>

---

## 项目概述

一个用于搜索动漫磁力链接与种子的Python库。它拥有强大的可扩展性, 支持通过插件系统从不同来源搜索动画资源,并能够处理磁力链接、文件大小转换等功能。

## 主要特性

- 支持多个资源站点的搜索功能
- 可扩展的插件系统
- 文件大小单位转换
- CSV导出功能
- 磁力链接处理
- 时间格式转换
- 错误处理机制

## 安装

Animag可以使用pip轻松地安装:

```commandline
pip install animag
```

## 使用示例

```python
# 导入搜索器类
from animag import Searcher

# 创建搜索器实例
searcher = Searcher(plugin_name='dmhy',
                    no_search_errors=True)

# 搜索动画
results = searcher.search("葬送的芙莉莲",
                          collected=True)

# 打印搜索结果
print(results)

"""
示例输出(2024年12月22日的结果):

Search completed successfully: 葬送的芙莉莲
[Anime(time='2024/10/20 12:23', title='[7³ACG\u200b] \u200b葬送的芙莉莲/Sousou no Frieren S01 | 01-28 [简繁字幕] BDrip 1080p AV1 OPUS 2.0\u200b\u200b\u200b', size='17.1GB', magnet='magnet:?xt=urn:btih:...

"""

# 转换所有结果的文件大小为GB
searcher.size_format_all('MB')

# 保存结果到CSV文件
searcher.save_csv("search_results.csv")
```

## 核心组件

### Anime类

`Anime`类用于表示单个动画资源的信息

#### 主要属性

- `time`: 发布时间
- `title`: 标题
- `size`: 文件大小
- `magnet`: 磁力链接
- `torrent`: 种子链接

#### 主要方法

- `size_format()`: 转换文件大小单位
- `set_timefmt()`: 转换时间格式

### Searcher类

`Searcher`类是搜索功能的核心实现

#### 主要功能

- 初始化搜索插件
- 执行搜索操作
- 处理搜索结果
- 导出数据

#### 主要方法

- `search()`: 搜索动画资源
- `size_format_all()`: 批量转换文件大小单位
- `save_csv()`: 将搜索结果保存为CSV文件
- `set_timefmt()`: 设置时间格式

## 错误处理

系统定义了多种错误类型:

- `PluginImportError`: 插件导入错误
- `SearchRequestError`: 搜索请求错误
- `SearchParseError`: 搜索结果解析错误
- `SizeFormatError`: 文件大小格式化错误
- `TimeFormatError`: 时间格式化错误
- `SaveCSVError`: CSV保存错误

## 配置选项

### 搜索器初始化选项

- `plugin_name`: 插件名称(默认:'dmhy')
- `parser`: 解析器选项
- `verify`: 验证选项
- `timefmt`: 时间格式
- `no_search_errors`: 是否忽略搜索错误

### 搜索选项

- `keyword`: 搜索关键词
- `collected`: 是否收集结果
- `proxies`: 代理设置
- `system_proxy`: 是否使用系统代理

## 自定义插件

Animag支持安装自己实现的搜索插件,插件类必须继承`BasePlugin`类,并实现`search()`方法。

### 示例插件

```python
# myplugin.py
# 文件名必须是小写的插件名称

from animag import BasePlugin, Anime, Searcher
from typing import List, Optional


class MyPlugin(BasePlugin):
    abstract = False  # 这一行必须设置,否则不会被识别为插件

    def __init__(self,
                 parser: Optional[str] = None,
                 verify: Optional[bool] = None,
                 timefmt: Optional[str] = None):
        # 插件初始化
        pass

    def search(self, keyword: str,
               collected: Optional[bool] = None,
               proxies: Optional[dict] = None,
               system_proxy: Optional[bool] = None,
               **extra_options) -> List[Anime] | None:
        # 实现搜索逻辑
        pass
```

### 安装插件

将自定义插件安装到animag/plugins目录后,在搜索器初始化时,指定插件名称为`myplugin`即可,如果没有安装至此目录,也可以手动将模块导入至命名空间。

```python
searcher = Searcher(plugin_name='myplugin')
```

## 命令行接口 (CLI)

项目附赠了一个CLI工具,使用 Rich 库实现美观的控制台输出,支持交互式选择。

### 命令行参数

```commandline
animag [-h] -s SEARCH [-p PLUGIN] [-c]
```

#### 必选参数

-s, --search: 搜索关键词

#### 可选参数

- `-h`, `--help`: 显示帮助信息
- `-p`, `--plugin`: 指定搜索插件(默认:'dmhy')
- `-c`, `--collected`: 启用季度全集搜索模式

### 使用示例

```commandline

# 基本搜索
animag -s "葬送的芙莉莲"

# 使用特定插件搜索
animag -s "葬送的芙莉莲" -p nyaa

# 搜索季度全集
animag -s "葬送的芙莉莲" -c
```

## 注意事项

1. 目前所有的插件都需要代理才能工作,确保正确配置代理设置
2. 时间格式必须符合Python的时间格式字符串规范

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/adogecheems/animag",
    "name": "animag",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "anime magnet torrent scrape spider rss expandable plugin acgrip dmhy nyaa tokyotosho miobt kisssub comicat",
    "author": "adogecheems",
    "author_email": "master@mmoe.work",
    "download_url": "https://files.pythonhosted.org/packages/76/8f/ea39b0ca6efc7ed498f035c3b8f5c1f3c11763493a1e31c6061b02db8b6f/animag-2.0.0.tar.gz",
    "platform": null,
    "description": "<h1 align=\"center\" style=\"font-size: 3rem; color: #1772b4\">Animag 2.0</h1>\n\n---\n\n## \u9879\u76ee\u6982\u8ff0\n\n\u4e00\u4e2a\u7528\u4e8e\u641c\u7d22\u52a8\u6f2b\u78c1\u529b\u94fe\u63a5\u4e0e\u79cd\u5b50\u7684Python\u5e93\u3002\u5b83\u62e5\u6709\u5f3a\u5927\u7684\u53ef\u6269\u5c55\u6027\uff0c \u652f\u6301\u901a\u8fc7\u63d2\u4ef6\u7cfb\u7edf\u4ece\u4e0d\u540c\u6765\u6e90\u641c\u7d22\u52a8\u753b\u8d44\u6e90\uff0c\u5e76\u80fd\u591f\u5904\u7406\u78c1\u529b\u94fe\u63a5\u3001\u6587\u4ef6\u5927\u5c0f\u8f6c\u6362\u7b49\u529f\u80fd\u3002\n\n## \u4e3b\u8981\u7279\u6027\n\n- \u652f\u6301\u591a\u4e2a\u8d44\u6e90\u7ad9\u70b9\u7684\u641c\u7d22\u529f\u80fd\n- \u53ef\u6269\u5c55\u7684\u63d2\u4ef6\u7cfb\u7edf\n- \u6587\u4ef6\u5927\u5c0f\u5355\u4f4d\u8f6c\u6362\n- CSV\u5bfc\u51fa\u529f\u80fd\n- \u78c1\u529b\u94fe\u63a5\u5904\u7406\n- \u65f6\u95f4\u683c\u5f0f\u8f6c\u6362\n- \u9519\u8bef\u5904\u7406\u673a\u5236\n\n## \u5b89\u88c5\n\nAnimag\u53ef\u4ee5\u4f7f\u7528pip\u8f7b\u677e\u5730\u5b89\u88c5\uff1a\n\n```commandline\npip install animag\n```\n\n## \u4f7f\u7528\u793a\u4f8b\n\n```python\n# \u5bfc\u5165\u641c\u7d22\u5668\u7c7b\nfrom animag import Searcher\n\n# \u521b\u5efa\u641c\u7d22\u5668\u5b9e\u4f8b\nsearcher = Searcher(plugin_name='dmhy',\n                    no_search_errors=True)\n\n# \u641c\u7d22\u52a8\u753b\nresults = searcher.search(\"\u846c\u9001\u7684\u8299\u8389\u83b2\",\n                          collected=True)\n\n# \u6253\u5370\u641c\u7d22\u7ed3\u679c\nprint(results)\n\n\"\"\"\n\u793a\u4f8b\u8f93\u51fa(2024\u5e7412\u670822\u65e5\u7684\u7ed3\u679c)\uff1a\n\nSearch completed successfully: \u846c\u9001\u7684\u8299\u8389\u83b2\n[Anime(time='2024/10/20 12:23', title='[7\u00b3ACG\\u200b] \\u200b\u846c\u9001\u7684\u8299\u8389\u83b2/Sousou no Frieren S01 | 01-28 [\u7b80\u7e41\u5b57\u5e55] BDrip 1080p AV1 OPUS 2.0\\u200b\\u200b\\u200b', size='17.1GB', magnet='magnet:?xt=urn:btih:...\n\n\"\"\"\n\n# \u8f6c\u6362\u6240\u6709\u7ed3\u679c\u7684\u6587\u4ef6\u5927\u5c0f\u4e3aGB\nsearcher.size_format_all('MB')\n\n# \u4fdd\u5b58\u7ed3\u679c\u5230CSV\u6587\u4ef6\nsearcher.save_csv(\"search_results.csv\")\n```\n\n## \u6838\u5fc3\u7ec4\u4ef6\n\n### Anime\u7c7b\n\n`Anime`\u7c7b\u7528\u4e8e\u8868\u793a\u5355\u4e2a\u52a8\u753b\u8d44\u6e90\u7684\u4fe1\u606f\n\n#### \u4e3b\u8981\u5c5e\u6027\n\n- `time`: \u53d1\u5e03\u65f6\u95f4\n- `title`: \u6807\u9898\n- `size`: \u6587\u4ef6\u5927\u5c0f\n- `magnet`: \u78c1\u529b\u94fe\u63a5\n- `torrent`: \u79cd\u5b50\u94fe\u63a5\n\n#### \u4e3b\u8981\u65b9\u6cd5\n\n- `size_format()`: \u8f6c\u6362\u6587\u4ef6\u5927\u5c0f\u5355\u4f4d\n- `set_timefmt()`: \u8f6c\u6362\u65f6\u95f4\u683c\u5f0f\n\n### Searcher\u7c7b\n\n`Searcher`\u7c7b\u662f\u641c\u7d22\u529f\u80fd\u7684\u6838\u5fc3\u5b9e\u73b0\n\n#### \u4e3b\u8981\u529f\u80fd\n\n- \u521d\u59cb\u5316\u641c\u7d22\u63d2\u4ef6\n- \u6267\u884c\u641c\u7d22\u64cd\u4f5c\n- \u5904\u7406\u641c\u7d22\u7ed3\u679c\n- \u5bfc\u51fa\u6570\u636e\n\n#### \u4e3b\u8981\u65b9\u6cd5\n\n- `search()`: \u641c\u7d22\u52a8\u753b\u8d44\u6e90\n- `size_format_all()`: \u6279\u91cf\u8f6c\u6362\u6587\u4ef6\u5927\u5c0f\u5355\u4f4d\n- `save_csv()`: \u5c06\u641c\u7d22\u7ed3\u679c\u4fdd\u5b58\u4e3aCSV\u6587\u4ef6\n- `set_timefmt()`: \u8bbe\u7f6e\u65f6\u95f4\u683c\u5f0f\n\n## \u9519\u8bef\u5904\u7406\n\n\u7cfb\u7edf\u5b9a\u4e49\u4e86\u591a\u79cd\u9519\u8bef\u7c7b\u578b\uff1a\n\n- `PluginImportError`: \u63d2\u4ef6\u5bfc\u5165\u9519\u8bef\n- `SearchRequestError`: \u641c\u7d22\u8bf7\u6c42\u9519\u8bef\n- `SearchParseError`: \u641c\u7d22\u7ed3\u679c\u89e3\u6790\u9519\u8bef\n- `SizeFormatError`: \u6587\u4ef6\u5927\u5c0f\u683c\u5f0f\u5316\u9519\u8bef\n- `TimeFormatError`: \u65f6\u95f4\u683c\u5f0f\u5316\u9519\u8bef\n- `SaveCSVError`: CSV\u4fdd\u5b58\u9519\u8bef\n\n## \u914d\u7f6e\u9009\u9879\n\n### \u641c\u7d22\u5668\u521d\u59cb\u5316\u9009\u9879\n\n- `plugin_name`: \u63d2\u4ef6\u540d\u79f0\uff08\u9ed8\u8ba4\uff1a'dmhy'\uff09\n- `parser`: \u89e3\u6790\u5668\u9009\u9879\n- `verify`: \u9a8c\u8bc1\u9009\u9879\n- `timefmt`: \u65f6\u95f4\u683c\u5f0f\n- `no_search_errors`: \u662f\u5426\u5ffd\u7565\u641c\u7d22\u9519\u8bef\n\n### \u641c\u7d22\u9009\u9879\n\n- `keyword`: \u641c\u7d22\u5173\u952e\u8bcd\n- `collected`: \u662f\u5426\u6536\u96c6\u7ed3\u679c\n- `proxies`: \u4ee3\u7406\u8bbe\u7f6e\n- `system_proxy`: \u662f\u5426\u4f7f\u7528\u7cfb\u7edf\u4ee3\u7406\n\n## \u81ea\u5b9a\u4e49\u63d2\u4ef6\n\nAnimag\u652f\u6301\u5b89\u88c5\u81ea\u5df1\u5b9e\u73b0\u7684\u641c\u7d22\u63d2\u4ef6\uff0c\u63d2\u4ef6\u7c7b\u5fc5\u987b\u7ee7\u627f`BasePlugin`\u7c7b\uff0c\u5e76\u5b9e\u73b0`search()`\u65b9\u6cd5\u3002\n\n### \u793a\u4f8b\u63d2\u4ef6\n\n```python\n# myplugin.py\n# \u6587\u4ef6\u540d\u5fc5\u987b\u662f\u5c0f\u5199\u7684\u63d2\u4ef6\u540d\u79f0\n\nfrom animag import BasePlugin, Anime, Searcher\nfrom typing import List, Optional\n\n\nclass MyPlugin(BasePlugin):\n    abstract = False  # \u8fd9\u4e00\u884c\u5fc5\u987b\u8bbe\u7f6e\uff0c\u5426\u5219\u4e0d\u4f1a\u88ab\u8bc6\u522b\u4e3a\u63d2\u4ef6\n\n    def __init__(self,\n                 parser: Optional[str] = None,\n                 verify: Optional[bool] = None,\n                 timefmt: Optional[str] = None):\n        # \u63d2\u4ef6\u521d\u59cb\u5316\n        pass\n\n    def search(self, keyword: str,\n               collected: Optional[bool] = None,\n               proxies: Optional[dict] = None,\n               system_proxy: Optional[bool] = None,\n               **extra_options) -> List[Anime] | None:\n        # \u5b9e\u73b0\u641c\u7d22\u903b\u8f91\n        pass\n```\n\n### \u5b89\u88c5\u63d2\u4ef6\n\n\u5c06\u81ea\u5b9a\u4e49\u63d2\u4ef6\u5b89\u88c5\u5230animag/plugins\u76ee\u5f55\u540e\uff0c\u5728\u641c\u7d22\u5668\u521d\u59cb\u5316\u65f6\uff0c\u6307\u5b9a\u63d2\u4ef6\u540d\u79f0\u4e3a`myplugin`\u5373\u53ef\uff0c\u5982\u679c\u6ca1\u6709\u5b89\u88c5\u81f3\u6b64\u76ee\u5f55\uff0c\u4e5f\u53ef\u4ee5\u624b\u52a8\u5c06\u6a21\u5757\u5bfc\u5165\u81f3\u547d\u540d\u7a7a\u95f4\u3002\n\n```python\nsearcher = Searcher(plugin_name='myplugin')\n```\n\n## \u547d\u4ee4\u884c\u63a5\u53e3 (CLI)\n\n\u9879\u76ee\u9644\u8d60\u4e86\u4e00\u4e2aCLI\u5de5\u5177\uff0c\u4f7f\u7528 Rich \u5e93\u5b9e\u73b0\u7f8e\u89c2\u7684\u63a7\u5236\u53f0\u8f93\u51fa\uff0c\u652f\u6301\u4ea4\u4e92\u5f0f\u9009\u62e9\u3002\n\n### \u547d\u4ee4\u884c\u53c2\u6570\n\n```commandline\nanimag [-h] -s SEARCH [-p PLUGIN] [-c]\n```\n\n#### \u5fc5\u9009\u53c2\u6570\n\n-s, --search: \u641c\u7d22\u5173\u952e\u8bcd\n\n#### \u53ef\u9009\u53c2\u6570\n\n- `-h`, `--help`: \u663e\u793a\u5e2e\u52a9\u4fe1\u606f\n- `-p`, `--plugin`: \u6307\u5b9a\u641c\u7d22\u63d2\u4ef6\uff08\u9ed8\u8ba4\uff1a'dmhy'\uff09\n- `-c`, `--collected`: \u542f\u7528\u5b63\u5ea6\u5168\u96c6\u641c\u7d22\u6a21\u5f0f\n\n### \u4f7f\u7528\u793a\u4f8b\n\n```commandline\n\n# \u57fa\u672c\u641c\u7d22\nanimag -s \"\u846c\u9001\u7684\u8299\u8389\u83b2\"\n\n# \u4f7f\u7528\u7279\u5b9a\u63d2\u4ef6\u641c\u7d22\nanimag -s \"\u846c\u9001\u7684\u8299\u8389\u83b2\" -p nyaa\n\n# \u641c\u7d22\u5b63\u5ea6\u5168\u96c6\nanimag -s \"\u846c\u9001\u7684\u8299\u8389\u83b2\" -c\n```\n\n## \u6ce8\u610f\u4e8b\u9879\n\n1. \u76ee\u524d\u6240\u6709\u7684\u63d2\u4ef6\u90fd\u9700\u8981\u4ee3\u7406\u624d\u80fd\u5de5\u4f5c\uff0c\u786e\u4fdd\u6b63\u786e\u914d\u7f6e\u4ee3\u7406\u8bbe\u7f6e\n2. \u65f6\u95f4\u683c\u5f0f\u5fc5\u987b\u7b26\u5408Python\u7684\u65f6\u95f4\u683c\u5f0f\u5b57\u7b26\u4e32\u89c4\u8303\n",
    "bugtrack_url": null,
    "license": "AGPLv3",
    "summary": "Anime magnet search library with strong expandability",
    "version": "2.0.0",
    "project_urls": {
        "Homepage": "https://github.com/adogecheems/animag"
    },
    "split_keywords": [
        "anime",
        "magnet",
        "torrent",
        "scrape",
        "spider",
        "rss",
        "expandable",
        "plugin",
        "acgrip",
        "dmhy",
        "nyaa",
        "tokyotosho",
        "miobt",
        "kisssub",
        "comicat"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0cf003b7e9e89a1d191c044ab2736ac890656ce3e68d899324dcebd4fb899275",
                "md5": "87c148bcf71de7f9f0d00b1f6dc83105",
                "sha256": "313fe02542c06f17f7426b94723aef94bd0a536bdcda5d1bfb7b4b0a84b92503"
            },
            "downloads": -1,
            "filename": "animag-2.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "87c148bcf71de7f9f0d00b1f6dc83105",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 19898,
            "upload_time": "2024-12-22T09:01:11",
            "upload_time_iso_8601": "2024-12-22T09:01:11.811426Z",
            "url": "https://files.pythonhosted.org/packages/0c/f0/03b7e9e89a1d191c044ab2736ac890656ce3e68d899324dcebd4fb899275/animag-2.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "768fea39b0ca6efc7ed498f035c3b8f5c1f3c11763493a1e31c6061b02db8b6f",
                "md5": "36b4877729b1ce37556aa80ea0662c1e",
                "sha256": "3307dea9c60941172d18f887082aafa715d0921333f0a95966dede133f759e0c"
            },
            "downloads": -1,
            "filename": "animag-2.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "36b4877729b1ce37556aa80ea0662c1e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 16713,
            "upload_time": "2024-12-22T09:01:14",
            "upload_time_iso_8601": "2024-12-22T09:01:14.474366Z",
            "url": "https://files.pythonhosted.org/packages/76/8f/ea39b0ca6efc7ed498f035c3b8f5c1f3c11763493a1e31c6061b02db8b6f/animag-2.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-22 09:01:14",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "adogecheems",
    "github_project": "animag",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "requests",
            "specs": []
        },
        {
            "name": "bs4",
            "specs": []
        },
        {
            "name": "lxml",
            "specs": []
        },
        {
            "name": "rich",
            "specs": []
        }
    ],
    "lcname": "animag"
}
        
Elapsed time: 0.94052s