JMComic-Crawler-Python/assets/docs/sources/tutorial/0_common_usage.md

7.9 KiB
Raw Blame History

常用类和方法

下载本子/章节

from jmcomic import *

# 下载id为438696的本子 (https://18comic.vip/album/438696)
download_album(438696)

# 下载章节 (https://18comic.vip/photo/438696)
download_photo(438696)

# 同时下载多个本子
download_album([123, 456, 789])

使用option定制化下载本子

如果你在下载本子时有一些定制化需求,

例如指定禁漫域名,使用代理,登录禁漫,图片格式转换等等,

那么你可以试试看jmcomic提供的option机制

from jmcomic import *

# 1. 在调用下载api前通过创建和使用option对象可以定制化下载行为。
# 推荐使用配置文件的方式来创建option对象
# 你可以配置很多东西比如代理、cookies、下载规则等等。
# 配置文件的语法参考: https://jmcomic.readthedocs.io/en/latest/option_file_syntax/
option = create_option_by_file('op.yml')  # 通过配置文件来创建option对象

# 2. 调用下载api把option作为参数传递 
download_album(123, option)
# 也可以使用下面这种面向对象的方式,是一样的
option.download_album(123)

获取本子/章节/图片的实体类,下载图片

from jmcomic import *

# 客户端
client = JmOption.default().new_jm_client()

# 本子实体类
album: JmAlbumDetail = client.get_album_detail('427413')


def fetch(photo: JmPhotoDetail):
    # 章节实体类
    photo = client.get_photo_detail(photo.photo_id, False)
    print(f'章节id: {photo.photo_id}')
    
    # 图片实体类
    image: JmImageDetail
    for image in photo:
        print(f'图片url: {image.img_url}')
        
    # 下载单个图片
    client.download_by_image_detail(image, './a.jpg')
    # 如果是已知未混淆的图片也可以直接使用url来下载
    random_image_domain = JmModuleConfig.DOMAIN_IMAGE_LIST
    client.download_image(f'https://{random_image_domain}/media/albums/416130.jpg', './a.jpg')
    

# 多线程发起请求
multi_thread_launcher(
    iter_objs=album,
    apply_each_obj_func=fetch
)

jmcomic异常处理示例

from jmcomic import *

# 客户端
client = JmOption.default().new_jm_client()

# 捕获jmcomic可能出现的异常
try:
    # 请求本子实体类
    album: JmAlbumDetail = client.get_album_detail('427413')
except MissingAlbumPhotoException as e:
    print(f'id={e.error_jmid}的本子不存在')
    
except JsonResolveFailException as e:
    print(f'解析json失败')
    # 响应对象
    resp = e.resp
    print(f'resp.text: {resp.text}, resp.status_code: {resp.status_code}')
    
except RequestRetryAllFailException as e:
    print(f'请求失败,重试次数耗尽')
    
except JmcomicException as e:
    # 捕获所有异常,用作兜底
    print(f'jmcomic遇到异常: {e}')

搜索本子

from jmcomic import *

client = JmOption.default().new_jm_client()

# 分页查询search_site就是禁漫网页上的【站内搜索】
page: JmSearchPage = client.search_site(search_query='+MANA +无修正', page=1)
# page默认的迭代方式是page.iter_id_title(),每次迭代返回 albun_id, title
for album_id, title in page:
    print(f'[{album_id}]: {title}')

# 直接搜索禁漫车号
page = client.search_site(search_query='427413')
album: JmAlbumDetail = page.single_album
print(album.tags)

搜索并下载本子

from jmcomic import *

option = JmOption.default()
client = option.new_jm_client()

tag = '無修正'
# 搜索标签可以使用search_tag。
# 搜索第一页。
page: JmSearchPage = client.search_tag(tag, page=1)

aid_list = []

for aid, atitle, tag_list in page.iter_id_title_tag():  # 使用page的iter_id_title_tag迭代器
    if tag in tag_list:
        print(f'[标签/{tag}] 发现目标: [{aid}]: [{atitle}]')
        aid_list.append(aid)

download_album(aid_list, option)

分类 / 排行榜

禁漫的分类是一个和搜索有些类似的功能。

搜索是按某一条件进行过滤。

分类没有过滤就是把某一类别category下的本子全都调出来。

禁漫的排行榜就是分类的一种形式

下面演示调用分类api

from jmcomic import *

# 创建客户端
op = JmOption.default()
cl = op.new_jm_client()

# 调用分类接口
# 根据下面的参数,这个调用的意义就是:
# 在全部分类下,选择所有时间范围,按观看数排序后,获取第一页的本子
page: JmCategoryPage = cl.categories_filter(
    page=1,
    time=JmMagicConstants.TIME_ALL,  # 时间选择全部具体可以写什么请见JmMagicConstants
    category=JmMagicConstants.CATEGORY_ALL,  # 分类选择全部具体可以写什么请见JmMagicConstants
    order_by=JmMagicConstants.ORDER_BY_LATEST,  # 按照观看数排序具体可以写什么请见JmMagicConstants
)

# 月排行底层实现也是调的categories_filter
page: JmCategoryPage = cl.month_ranking(1)
# 周排行
page: JmCategoryPage = cl.week_ranking(1)

# 循环获取分页,使用 cl.categories_filter_gen
for page in cl.categories_filter_gen(page=1, # 起始页码
                                     # 下面是分类参数
                                     time=JmMagicConstants.TIME_WEEK,
                                     category=JmMagicConstants.CATEGORY_ALL,
                                     order_by=JmMagicConstants.ORDER_BY_VIEW,
                                     ):
    for aid, atitle in page:
        print(aid, atitle)

高级搜索(分类/副分类)

禁漫网页端的搜索除了常规条件,还支持【分类】和【副分类】的搜索。

在任一搜索页面,你会看到本子图的右上方有两个标签。左边的是【分类】,右边的是【副分类】。

下面演示代码如何编写。

  • 注意!!禁漫移动端没有提供如下功能,以下代码仅对网页端生效。
# 在编写代码前,建议先熟悉禁漫网页的搜本功能,下面的代码都是对照网页编写的。
# 网页搜索示例https://18comic.vip/search/photos/doujin/sub/CG?main_tag=0&search_query=mana&page=1&o=mr&t=a

from jmcomic import *

op = create_option_by_file('op.yml')
# 创建网页端client
html_cl = op.new_jm_client(impl='html')

# 使用站内搜索,指定【分类】和【副分类】
# 分类 = JmMagicConstants.CATEGORY_DOUJIN = 同人本
# 副分类 = JmMagicConstants.SUB_DOUJIN_CG = CG本
# 实际URLhttps://18comic.vip/search/photos/doujin/sub/CG?main_tag=0&search_query=mana&page=1&o=mr&t=a
page = html_cl.search_site(search_query='mana',
                           category=JmMagicConstants.CATEGORY_DOUJIN,
                           sub_category=JmMagicConstants.SUB_DOUJIN_CG,
                           page=1,
                           )
# 打印page内容
for aid, atitle in page.iter_id_title():
    print(aid, atitle)

# 循环获取分页
for page in html_cl.search_gen(search_query='mana',
                               category=JmMagicConstants.CATEGORY_DOUJIN,
                               sub_category=JmMagicConstants.SUB_DOUJIN_CG,
                               page=1,  # 起始页码
                               ):
    # 打印page内容
    for aid, atitle in page.iter_id_title():
        print(aid, atitle)

手动创建Client

# 默认的使用方式是先创建optionoption封装了所有配置然后由option.new_jm_client() 创建客户端client使用client可以访问禁漫接口

# 下面演示直接构造client的方式
from jmcomic import *

"""
创建JM客户端

:param postman: 负责实现HTTP请求的对象持有cookies、headers、proxies等信息
:param domain_list: 禁漫域名
:param retry_times: 重试次数
"""

# 网页端
cl = JmHtmlClient(
    postman=JmModuleConfig.new_postman(),
    domain_list=['18comic.vip'],
    retry_times=1
)

# API端APP
cl = JmApiClient(
    postman=JmModuleConfig.new_postman(),
    domain_list=JmModuleConfig.DOMAIN_API_LIST,
    retry_times=1
)