jmcomic Python API

repository·master·Indexed 27 days ago

https://github.com/hect0x7/jmcomic-crawler-python

A Python API and CLI tool for crawling and downloading content from JMComic (禁漫天堂), supporting both web and mobile interfaces. It features robust anti-bot bypassing, plugin support, and integration with GitHub Actions. The library provides synchronous and asynchronous methods for downloading albums and photos, customizable directory rules, and support for image decoding and format conversion.

Tokens
21.5K
Snippets
70
Records
126
Agent score
92%

What's inside jmcomic

  1. Understand the Plugin Mechanism

    master

    The plugin mechanism (introduced in v2.2.0) allows for flexible, non-intrusive functional enhancements. Plugins are automatically executed when specific events occur. You can configure plugins in your option configuration file.

    Built-in events include:

    • after_init: Triggered after the option object is created.
    • before_image: Before downloading an image.
    • before_album: Before downloading an album.
    • before_photo: Before downloading a chapter.
    • after_image: After downloading an image.
    • after_album: After downloading an album.
    • after_photo: After downloading a chapter.
  2. Project Overview and Features

    master

    jmcomic is a Python-based crawler designed to download content from JMComic. It supports both Async and Sync APIs and includes features to bypass Cloudflare protection and support the latest encryption/decryption algorithms used by the JMComic app.

    Key Features:

    • Multiple Interfaces: Supports Web and Mobile interfaces with easy switching.
    • High Performance: Multi-threaded downloading (one thread per image) and automatic retry/domain switching.
    • Extensibility: A powerful plugin system and support for custom callbacks (pre/post download for chapters/images).
    • Customizable Configuration: Control domains, client implementations, disk caching, concurrent download counts, file formats, image storage rules, metadata (headers, cookies, proxies), and Chinese character conversion (Simplified/Traditional).
    • Plugin Support: Includes plugins for login, tracking new chapters, exporting bookmarks to CSV, merging images into PDF or long PNGs, archiving, and cookie synchronization.
  3. Project Features and Capabilities

    master

    The jmcomic crawler provides several advanced features for downloading content:

    • Dual API Support: Compatible with both Async and Sync APIs.
    • Bypass Mechanisms: Includes Cloudflare bot protection bypass and support for the latest JM APP encryption algorithms (1.6.3).
    • Client Modes: Supports both Web (high efficiency, but subject to regional restrictions) and Mobile (high compatibility, no IP restrictions) clients.
    • High Performance: Supports multi-threaded downloads with fine-grained threading per image.
    • Extensibility:
      • Supports custom callbacks before/after downloading albums, chapters, or images.
      • Allows customization of core classes: Downloader, Option, Client, and entity classes.
      • Plugin System: Enables functional extensions like login plugins, PDF/PNG merging, Zip compression, and cookie extraction.
    • Flexible Configuration: Supports various formats for generating Option objects, including request domains, disk cache settings, download paths, and metadata (headers, cookies, proxies).
  4. Download an album using an Option configuration file

    master

    For advanced configurations (e.g., changing image formats, setting proxies, or using plugins), create a configuration file (e.g., option.yml) and load it using jmcomic.create_option_by_file().

    Example option.yml to convert images to PNG:

    download:
      image:
        suffix: .png

    Python usage:

    import jmcomic
    
    # Create an option object from your config file
    option = jmcomic.create_option_by_file('D:/option.yml')
    
    # Download the album using the option object
    jmcomic.download_album(123, option)
    # Alternatively: option.download_album(123)
    import jmcomic
    
    option = jmcomic.create_option_by_file('D:/option.yml')
    jmcomic.download_album(123, option)
  5. Customize download directory names with DirRule and f-string syntax

    master

    You can define custom download paths using the dir_rule.rule configuration. This supports f-string template syntax where you use {variable_name} to inject entity attributes into the path.

    Syntax Rules:

    • Use / as a separator (recommended): Bd / {Atitle} / {Pname}.
    • Alternatively, use _ as a separator: Bd_{Atitle}_{Pname}.
    • Important: Do not mix / and _. If your folder name needs an underscore, use / as the primary separator (e.g., Bd / {Aid}_{Atitle}).
    • Bd is a special segment representing the base_dir and should typically be placed at the beginning.

    Variables are prefixed by A (for Album/本子) or P (for Photo/章节).

    dir_rule:
      base_dir: D:/a/b/c/
      rule: Bd / {Atitle}
  6. Deeply customize logging behavior

    master

    For advanced logging requirements, there are two primary interception methods:

    1. Modify jm_logger (Recommended/Standard): Use this to change log output destinations (e.g., files, monitoring services, backends), adjust display formats, or implement custom filtering.
    2. Take over EXECUTOR_LOG (Advanced/Deep Customization): Use this if you need to completely reshape the log distribution logic or bridge logs directly to third-party systems that do not follow the standard Python logging protocol.
  7. Export and download JMComic favorites via GitHub Actions

    master

    You can automate the export and download of your JMComic favorites data using a GitHub Actions workflow. This process involves forking the repository, configuring your credentials as GitHub Secrets, and running the specific workflow.

    Prerequisites

    1. Fork the repository: Visit https://github.com/hect0x7/JMComic-Crawler-Python/fork and click Create fork.
    2. Enable Actions: Ensure GitHub Actions are enabled in your forked repository settings.

    To prevent leaking your credentials in the Action logs, use GitHub Secrets instead of manual input.

    1. Navigate to https://github.com/[YOUR_USERNAME]/JMComic-Crawler-Python/settings/secrets/actions.
    2. Add the following secrets:
      • JM_USERNAME: Your JMComic username.
      • JM_PASSWORD: Your JMComic password.
      • ZIP_PASSWORD: The password for the resulting compressed file.

    Running the Workflow

    1. Go to the workflow page: https://github.com/[YOUR_USERNAME]/JMComic-Crawler-Python/actions/workflows/export_favorites.yml.
    2. Select the export_favorites.yml workflow.
    3. Click Run workflow.
      • If you configured Secrets in the previous step, leave the input fields empty.
      • If you did not use Secrets, you must enter your username, password, and zip password in the input fields. Warning: This will expose your credentials in the Action logs. Delete the workflow run immediately after completion if you use this method.
    4. Once the workflow run turns green (completed), scroll to the bottom of the run summary to download your files.
  8. Filter categories and rankings

    master

    To filter categories or rankings, use categories_filter for a single page or categories_filter_gen as an asynchronous generator for automatic pagination. Use JmMagicConstants to specify time, category, and sort order.

    import asyncio
    from jmcomic import JmOption, JmMagicConstants
    
    async def main():
        async with JmOption.default().new_jm_async_client() as cl:
            # Get the first page of albums sorted by views
            page = await cl.categories_filter(
                page=1,
                time=JmMagicConstants.TIME_ALL,
                category=JmMagicConstants.CATEGORY_ALL,
                order_by=JmMagicConstants.ORDER_BY_VIEW,
            )
            
            for aid, atitle in page:
                print(aid, atitle)
    
            # Use generator for all pages
            async for page in cl.categories_filter_gen(
                time=JmMagicConstants.TIME_ALL,
                category=JmMagicConstants.CATEGORY_ALL,
                order_by=JmMagicConstants.ORDER_BY_VIEW,
            ):
                print(page.page)
    
    asyncio.run(main())