Skip to content

Instantly share code, notes, and snippets.

@Aloxaf
Created November 26, 2019 05:19

Revisions

  1. Aloxaf created this gist Nov 26, 2019.
    128 changes: 128 additions & 0 deletions sync_from_pixiv.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,128 @@
    #!/usr/bin/python

    from pixivpy3 import *

    from pathlib import Path
    from typing import *
    from concurrent import futures
    from os import system
    import json


    def get_tags_from_pixiv():
    """
    扫描本地图片, 获取图片信息并存储在 ./info.json 中
    :return:
    """
    # 登录 P 站
    api = AppPixivAPI(proxies={"https": "socks5h://127.0.0.1:8877"})
    api.set_accept_language("zh-cn")
    api.login('username', 'password')

    # 加载旧数据
    data_path = Path('./info.json')
    data = json.load(data_path.open('r'))

    def dump_data():
    json.dump(data, data_path.open('w'), ensure_ascii=False, indent=2)

    # 获取本地 illust 列表, 去除已获取部分
    illusts = Path("/home/aloxaf/Pictures/小萝莉").rglob("illust_*")
    illusts = set(f.name.split('_')[1] for f in illusts)
    illusts = filter(lambda x: data.get(x) is None, illusts)

    for i, pid in enumerate(illusts):

    print(f"\r{i}", end="")

    info = api.illust_detail(pid)

    # 作品可能被删除, 需要检查一下
    if error := info.get('error'):
    print(f'\n{error}')
    else:
    data[pid] = info['illust']

    if i % 10 == 0:
    dump_data()

    dump_data()


    def add_tags_for_local():
    """
    使用 exiftool 为本地图片添加 metadata, 以供 digiKam 导入
    :return:
    """
    # 加载信息
    data_path = Path('./info.json')
    data = json.load(data_path.open('r'))

    # 获取需要处理的图片列表
    tagged_path = Path('./tagged.json')
    tagged = set(json.load(tagged_path.open('r')))

    illusts = Path("/home/aloxaf/Pictures/小萝莉").rglob("illust_*")

    # exiftool 速度太慢, 开四线程
    with futures.ThreadPoolExecutor(max_workers=4) as executor:
    tasks = []
    for file in illusts:
    pid = file.name.split('_')[1]

    # 过滤掉已经添加过的图片和没有信息可以添加的图片
    if file.name in tagged or (info := data.get(pid)) is None:
    continue

    tagged.add(file.name)
    tasks.append(executor.submit(add_tags_for_image, file, info))

    futures.wait(tasks)

    json.dump(list(tagged), tagged_path.open('w'), indent=2)


    Json = Union[bool, float, str, int, Dict[str, 'Json'], List['Json']]


    def add_tags_for_image(file: Path, info: Json):
    """
    为图片添加 metada
    :param file: 图片地址
    :param info: 图片信息
    :return:
    """
    # 等待添加的 metadata
    title = info['title']
    author = info['user']['name']
    caption = info['caption'] or ' ' # 如果没有描述, 添加一个空格, 否则作者不会被导入
    tags = [tag.get('translated_name') or tag['name'] for tag in info['tags']]
    tags = ', '.join(tags).replace('/', '\\')

    attrs = ' '.join([
    f'"-Title={title}"',
    f'"-Description= "',
    f'"-CaptionsAuthorNames={author}"',
    f'"-TagsList={tags}"',
    # f'"-Author="',
    # f'"-CatalogSets="'
    # f'"-Categories="',
    # f'"-HierarchicalSubject="',
    # f'"-LastKeywordXMP="',
    # f'"-Subject="',
    # f'"-Keywords="',
    # f'"-Caption="',
    # f'"-CatalogSets="',
    # f'"-ObjectName="',
    ])

    system(f'exiftool -sep ", " {attrs} {file} -overwrite_original')


    def main():
    get_tags_from_pixiv()
    add_tags_for_local()


    if __name__ == "__main__":
    main()