• 李白传

    📖 图书详细信息

    书名: 李白传
    作者: 李长之
    出版商: 浙江文艺出版社
    语言: zh
    出版日期: 2019-03-13T16:00:00+00:00

    🔍 标识符

    • unknown: 51516b43-5cf2-44d7-a2d5-bc55c2c977fc
    • uuid_id: a0c27092-83a8-4347-836b-8e293a079bea
    • unknown: a0c27092-83a8-4347-836b-8e293a079bea
  • 图解维摩诘经 (图解经典系列)

    📖 图书详细信息

    书名: 图解维摩诘经 (图解经典系列)
    作者: 释心田
    出版商: 紫禁城出版社
    语言: zh
    出版日期: 2009-12-01

    🔍 标识符

    • bookid: urn:uuid:273fd756-62f2-4858-8d67-99e08f24bba9
    • unknown: B0084Y7VWO
  • 寿康宝鉴

    📖 图书详细信息

    书名: 寿康宝鉴
    作者: 印光大师
    出版商: 未知
    语言: zh
    出版日期: 2016-04-21T16:00:00+00:00

    🔍 标识符

    • uid: 24749893
    • unknown: 49896465-e631-4fdb-a4bb-027a2a4df188
    • unknown: B01EMYAYPK
  • Debain 12 下qBittorrent(下载)+Jackett(搜索)+ FlareSolverr()docker安装下载


    效果:


    (1)系统环境

    • Debian 12
    • Docker

    (2)安装qBittorrent:docker-compose.yml

    ---
    services:
      qbittorrent:
        image: linuxserver/qbittorrent
        container_name: qbittorrent
        environment:
          - PUID=1000
          - PGID=1000
          - TZ=Etc/UTC
          - WEBUI_PORT=WEB端口号
          - TORRENTING_PORT=6881
        volumes:
          - /home/homeadmin/qbittorrent/config:/config
          - /磁盘/Movie:/downloads #optional
        ports:
          - 端口号:8085
          - 6881:6881
          - 6881:6881/udp
        restart: unless-stopped

    (3)安装Jackett,docker-compose.yml

    version: '3.8'
    services:
      jackett:
        image: linuxserver/jackett:latest
        container_name: jackett
        restart: unless-stopped
        environment:
          - PUID=1000
          - PGID=1000
          - TZ=Asia/Shanghai
          - AUTO_UPDATE=true
        volumes:
          - ./config:/config
          -  /srv/dev-disk-by-uuid-61b2ae38-2385-4cd5-8799-5ed424e53da0/Movie:/downloads
        ports:
          - "9117:9117"
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:9117/UI/Dashboard"]
          interval: 30s
          timeout: 10s
          retries: 3

    (4)配置qBittorrent 支持 Jackett

    • 需要修改API key和对应的IP地址
    配置jackett:~/qbittorrent/config/qBittorrent/nova3/engines
    
    {
    "api_key": "API key",
    "thread_count": 20,
    "tracker_first": false,
    "url": "http://IP地址:9117"
    }
    • API key

    (4)安装配置FlareSolverr

    
    docker run -d \
      --name=flaresolverr \
      -p 8191:8191 \
      -e LOG_LEVEL=info \
      --restart unless-stopped \
      ghcr.io/flaresolverr/flaresolverr:latest

    检查是否安装成功:

    1.要打开防火墙

    2.若在不同设备(如 FlareSolverr 在 172.17.0.2,Jackett 在 192.168.2.240):在 Jackett 运行的设备上,通过命令行执行curl http://IP地址:8191/v1(需安装 curl 工具),若返回类似{"status":"ok","message":"FlareSolverr is ready"}的响应,说明 API 可访问;若提示 “连接超时”,需检查两台设备的网络互通(关闭防火墙、确保在同一局域网)。

    3.或者访问http://ip地址:8191,显示{“msg”: “FlareSolverr is ready!”, “version”: “3.4.6”, “userAgent”: “Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36”}

    (5)Jackett配置FlareSolverr

    • FlareSolverr API中填写
  • 如何把epub文件批量上载到wordpress平台-2025.12

    效果展示:


    (1)系统环境:

    • debain 12
    • python 虚拟环境

    (2)步骤:

    • 创建虚拟环境:source epubtowordpress/bin/activate
    • 执行命令:python3 epubtowordpress.py

    (3)epubtowordpress.py 代码

    #!/usr/bin/env python3
    """
    EPUB到WordPress发布脚本 - 修复版
    解决tuple indices must be integers or slices, not str错误
    """
    
    import os
    import glob
    import zipfile
    import shutil
    import tempfile
    import time
    import json
    from ebooklib import epub
    from wordpress_xmlrpc import Client, WordPressPost
    from wordpress_xmlrpc.methods.posts import NewPost
    from wordpress_xmlrpc.methods.media import UploadFile
    from wordpress_xmlrpc.compat import xmlrpc_client
    
    class EpubToWordPress:
        def __init__(self, wp_url, wp_username, wp_password):
            """
            初始化发布器
            
            Args:
                wp_url: WordPress网站地址
                wp_username: WordPress用户名
                wp_password: WordPress密码
            """
            self.wp_url = wp_url.rstrip('/')
            self.wp_username = wp_username
            self.wp_password = wp_password
            self.client = Client(f"{wp_url}/xmlrpc.php", wp_username, wp_password)
        
        def safe_extract_metadata(self, book, namespace, name):
            """
            安全提取元数据,修复tuple indices错误
            """
            try:
                metadata = book.get_metadata(namespace, name)
                if not metadata:
                    return ""
                
                # 处理 [(value, attributes)] 格式,取元组第一个元素
                if isinstance(metadata, list) and len(metadata) > 0:
                    item = metadata[0]  # 取列表第一个元素(元组)
                    if isinstance(item, (tuple, list)) and len(item) > 0:
                        return str(item[0])  # 取元组第一个元素(实际值)
                    elif isinstance(item, str):
                        return item
                    else:
                        return str(item)
                return ""
            except Exception as e:
                print(f"元数据提取警告 ({namespace}/{name}): {e}")
                return ""
        
        def safe_extract_metadata_list(self, book, namespace, name):
            """
            安全提取元数据列表
            """
            results = []
            try:
                metadata = book.get_metadata(namespace, name)
                if not metadata:
                    return results
                
                for item in metadata:
                    if isinstance(item, (tuple, list)) and len(item) > 0:
                        results.append(str(item[0]))  # 修复:取元组第一个元素
                    elif isinstance(item, str):
                        results.append(item)
                    else:
                        results.append(str(item))
                return results
            except Exception as e:
                print(f"元数据列表提取警告: {e}")
                return []
        
        def extract_complete_metadata(self, epub_path):
            """
            提取EPUB文件的完整元数据
            """
            try:
                print(f"正在解析EPUB文件: {os.path.basename(epub_path)}")
                
                if not self.check_epub_integrity(epub_path):
                    print("文件完整性检查失败")
                    return None
                
                book = epub.read_epub(epub_path)
                
                metadata = {
                    'title': self.safe_extract_metadata(book, 'DC', 'title') or 
                            os.path.basename(epub_path).replace('.epub', ''),
                    'authors': self.safe_extract_metadata_list(book, 'DC', 'creator'),
                    'publisher': self.safe_extract_metadata(book, 'DC', 'publisher'),
                    'language': self.safe_extract_metadata(book, 'DC', 'language'),
                    'description': self.safe_extract_metadata(book, 'DC', 'description'),
                    'dates': self.safe_extract_metadata_list(book, 'DC', 'date'),
                    'subjects': self.safe_extract_metadata_list(book, 'DC', 'subject'),
                    'identifiers': [],
                    'filename': os.path.basename(epub_path)
                }
                
                # 特殊处理标识符(修复元组取值)
                try:
                    identifiers = book.get_metadata('DC', 'identifier')
                    if identifiers:
                        for identifier in identifiers:
                            if isinstance(identifier, (tuple, list)) and len(identifier) > 0:
                                id_value = str(identifier[0])  # 修复:取元组第一个元素
                                id_type = 'unknown'
                                if len(identifier) > 1 and hasattr(identifier[1], 'get'):
                                    id_type = identifier[1].get('id', 'unknown')
                                metadata['identifiers'].append({
                                    'type': id_type,
                                    'value': id_value
                                })
                except Exception as e:
                    print(f"标识符提取警告: {e}")
                
                print(f"✓ 成功提取元数据: {metadata['title']}")
                return metadata
                
            except Exception as e:
                print(f"✗ 解析EPUB文件失败: {e}")
                return None
        
        def check_epub_integrity(self, epub_path):
            """检查EPUB文件完整性"""
            try:
                with zipfile.ZipFile(epub_path, 'r') as zip_ref:
                    return zip_ref.testzip() is None
            except Exception as e:
                print(f"文件完整性检查错误: {e}")
                return False
        
        def upload_epub_file(self, epub_path):
            """上传EPUB文件到WordPress媒体库"""
            try:
                print(f"正在上传文件: {os.path.basename(epub_path)}")
                
                data = {
                    'name': os.path.basename(epub_path),
                    'type': 'application/epub+zip'
                }
                
                with open(epub_path, 'rb') as f:
                    data['bits'] = xmlrpc_client.Binary(f.read())
                
                response = self.client.call(UploadFile(data))
                
                print(f"✓ 文件上传成功: {response['url']}")
                return {
                    'url': response['url'],
                    'id': response['id']
                }
                
            except Exception as e:
                print(f"✗ 文件上传失败: {e}")
                return None
        
        def create_post(self, metadata, file_url):
            """创建WordPress文章"""
            try:
                post = WordPressPost()
                post.title = metadata['title']
                post.content = self.generate_post_content(metadata, file_url)
                post.post_status = 'publish'
                
                if metadata['description']:
                    post.excerpt = metadata['description'][:300]
                else:
                    post.excerpt = f"{metadata['title']} - 电子书下载"
                
                tags = ['EPUB', '电子书' ]
                if metadata['subjects']:
                    tags.extend(metadata['subjects'][:3])
                
                categories = ['书籍分享', 'sjfx']
                if metadata['publisher']:
                    tags.append(metadata['publisher'])
                
                post.terms_names = {
                    'post_tag': tags,
                    'category': categories
                }
                
                result = self.client.call(NewPost(post))
                
                if result:
                    print(f"✓ 文章发布成功: {metadata['title']}")
                    return True
                else:
                    print(f"✗ 文章发布失败")
                    return False
                    
            except Exception as e:
                print(f"✗ 文章创建失败: {e}")
                return False
        
        def generate_post_content(self, metadata, file_url):
            """生成文章内容HTML"""
            content = f"""
            <div class="epub-book-details">
                <h2>📖 图书详细信息</h2>
                <table class="book-info">
                    <tr><th>书名:</th><td>{metadata['title']}</td></tr>
                    <tr><th>作者:</th><td>{', '.join(metadata['authors']) if metadata['authors'] else '未知'}</td></tr>
                    <tr><th>出版商:</th><td>{metadata['publisher'] or '未知'}</td></tr>
                    <tr><th>语言:</th><td>{metadata['language'] or '未知'}</td></tr>
                    <tr><th>出版日期:</th><td>{', '.join(metadata['dates']) if metadata['dates'] else '未知'}</td></tr>
                </table>
            """
            
            if metadata['identifiers']:
                content += "<h3>🔍 标识符</h3><ul>"
                for identifier in metadata['identifiers']:
                    content += f'<li><strong>{identifier["type"]}:</strong> {identifier["value"]}</li>'
                content += "</ul>"
            
            if metadata['description']:
                content += f'<h3>📝 内容简介</h3><div class="description">{metadata["description"]}</div>'
            
            if metadata['subjects']:
                content += f'<h3>🏷️ 主题分类</h3><p>{", ".join(metadata["subjects"])}</p>'
            
            content += f"""
            <div class="download-section">
                <h3>⬇️ 下载链接</h3>
                <p><a href="{file_url}" class="download-button" download="{metadata['filename']}">
                    📥 下载 EPUB 文件 ({metadata['filename']})
                </a></p>
            </div>
            
            <style>
                .book-info {{
                    border-collapse: collapse;
                    width: 100%;
                    margin: 20px 0;
                    font-size: 14px;
                }}
                .book-info th, .book-info td {{
                    border: 1px solid #ddd;
                    padding: 12px;
                    text-align: left;
                }}
                .book-info th {{
                    background-color: #f5f5f5;
                    width: 120px;
                    font-weight: bold;
                }}
                .download-button {{
                    display: inline-block;
                    padding: 12px 24px;
                    background-color: #0073aa;
                    color: white;
                    text-decoration: none;
                    border-radius: 5px;
                    font-weight: bold;
                    font-size: 16px;
                }}
                .download-button:hover {{
                    background-color: #005a87;
                }}
                .description {{
                    line-height: 1.6;
                    padding: 15px;
                    background-color: #f8f9fa;
                    border-radius: 5px;
                    margin: 15px 0;
                }}
            </style>
            """
            
            return content
        
        def process_single_epub(self, epub_path):
            """处理单个EPUB文件"""
            print(f"\n{'='*60}")
            print(f"处理文件: {os.path.basename(epub_path)}")
            
            metadata = self.extract_complete_metadata(epub_path)
            if not metadata:
                return {'file': epub_path, 'status': 'metadata_failed'}
            
            upload_result = self.upload_epub_file(epub_path)
            if not upload_result:
                return {'file': epub_path, 'status': 'upload_failed'}
            
            if self.create_post(metadata, upload_result['url']):
                return {
                    'file': epub_path, 
                    'status': 'success', 
                    'title': metadata['title'],
                    'url': upload_result['url']
                }
            else:
                return {'file': epub_path, 'status': 'publish_failed'}
        
        def process_directory(self, directory='.'):
            """处理目录中的所有EPUB文件"""
            epub_files = glob.glob(os.path.join(directory, "*.epub"))
            
            if not epub_files:
                print("在当前目录下未找到EPUB文件")
                return []
            
            print(f"找到 {len(epub_files)} 个EPUB文件,开始处理...")
            
            results = []
            for epub_path in epub_files:
                result = self.process_single_epub(epub_path)
                results.append(result)
                time.sleep(2)
            
            self.print_summary(results)
            return results
        
        def print_summary(self, results):
            """打印处理结果摘要"""
            success_count = sum(1 for r in results if r['status'] == 'success')
            failed_count = len(results) - success_count
            
            print(f"\n{'='*60}")
            print(f"处理完成摘要:")
            print(f"  ✅ 成功: {success_count} 个文件")
            print(f"  ❌ 失败: {failed_count} 个文件")
            
            if success_count > 0:
                print(f"\n成功发布的文章:")
                for result in results:
                    if result['status'] == 'success':
                        print(f"  - {result['title']}")
            
            if failed_count > 0:
                print(f"\n失败的文件:")
                for result in results:
                    if result['status'] != 'success':
                        status_map = {
                            'metadata_failed': '元数据提取失败',
                            'upload_failed': '文件上传失败',
                            'publish_failed': '文章发布失败'
                        }
                        print(f"  - {os.path.basename(result['file'])}: {status_map[result['status']]}")
            
            print(f"{'='*60}")
    
    def main():
        """主函数 - 配置和使用发布器"""
       
        # WordPress配置信息
        WP_CONFIG = {
            'url': 'http://ip地址:端口号',  # 替换为你的WordPress地址
            'username': '用户名',              # 替换为你的用户名
            'password': '密码!',              # 替换为你的密码或应用密码
        }
    
    
        
        # 创建发布器实例
        publisher = EpubToWordPress(
            wp_url=WP_CONFIG['url'],
            wp_username=WP_CONFIG['username'],
            wp_password=WP_CONFIG['password']
        )
        
        print("开始处理EPUB文件...")
        results = publisher.process_directory('.')
        
        # 保存处理结果到JSON文件
        with open('epub_publishing_results.json', 'w', encoding='utf-8') as f:
            json.dump(results, f, ensure_ascii=False, indent=2)
        
        print("\n详细结果已保存到: epub_publishing_results.json")
    
    if __name__ == "__main__":
        main()
    
  • Grit

    📖 图书详细信息

    书名: Grit
    作者: Angela Duckworth
    出版商: Scribner
    语言: En
    出版日期: 未知

    🔍 标识符

    • p9781501111129: 9781501111129

    📝 内容简介

    In this must-read book for anyone striving to succeed, pioneering psychologist Angela Duckworth shows parents, students, educators, athletes, and business people—both seasoned and new—that the secret to outstanding achievement is not talent but a special blend of passion and persistence she calls “grit.”
    Drawing on her own powerful story as the daughter of a scientist who frequently noted her lack of “genius,” Duckworth, now a celebrated researcher and professor, describes her early eye-opening stints in teaching, business consulting, and neuroscience, which led to the hypothesis that what really drives success is not “genius” but a unique combination of passion and long-term perseverance.

    In Grit, she takes readers into the field to visit cadets struggling through their first days at West Point, teachers working in some of the toughest schools, and young finalists in the National Spelling Bee. She also mines fascinating insights from history and…
  • Endurance

    📖 图书详细信息

    书名: Endurance
    作者: Alfred Lansing
    出版商: Basic Books
    语言: en
    出版日期: 未知

    🔍 标识符

    • p9780306817731: 978-0-3068-1773-1

    📝 内容简介

    The astonishing saga of polar explorer Ernest Shackleton’s survival for over a year on the ice-bound Antarctic seas, as Time magazine put it, “defined heroism.” Alfred Lansing’s scrupulously researched and brilliantly narrated book — with over 200,000 copies sold — has long been acknowledged as the definitive account of the Endurance’s fateful trip. To write their authoritative story, Lansing consulted with ten of the surviving members and gained access to diaries and personal accounts by eight others. The resulting book has all the immediacy of a first-hand account, expanded with maps and illustrations especially for this edition.

  • 人生精进指南(套装共5册)

    📖 图书详细信息

    书名: 人生精进指南(套装共5册)
    作者: 蔡垒磊, 安杰拉•达克沃思, 古典, 罗伯特•西奥迪尼, 史蒂夫•马丁, 诺瓦•戈尔茨坦, 成甲
    出版商: 中信出版社
    语言: zh
    出版日期: 2016-11-17

    🔍 标识符

    • bookid: urn:uuid:273fd756-62f2-4858-8d67-99e08f24bba9
    • unknown: B075JF5L8W
  • 译文纪实·熬:极地求生700天

    📖 图书详细信息

    书名: 译文纪实·熬:极地求生700天
    作者: 【美】阿尔弗雷德·兰辛, 岱冈, ePUBw.COM
    出版商: 上海译文出版社
    语言: 未知
    出版日期: 2017-02-28T16:00:00+00:00

    🔍 标识符

    • bookid: urn:uuid:273fd756-62f2-4858-8d67-99e08f24bba9
    • unknown: f8a7ec17-5385-4e45-91da-0b864b8e9ea5
    • unknown: 64f9dca4-68ce-4777-90d4-cc8d1ffdd920
    • unknown: 9787532773237
  • 坚毅

    📖 图书详细信息

    书名: 坚毅
    作者: [ 美] 安杰拉·达克沃思
    出版商: 中信出版社
    语言: zh
    出版日期: 2017-05-31T16:00:00+00:00

    🔍 标识符

    • uuid_id: 22363b5a-e5da-4d78-92ea-ccb1872c40a5
    • unknown: e653ef43-fde0-4fb4-815c-5591c48f5d2b
    • unknown: B072VC6XQ7
    • unknown: 9787508673868