fukubucho_
@fukubucho_

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

pixivダウンローダの自己再起動プログラムを知りたい

@yuki_2020 さんのhttps://qiita.com/yuki_2020/items/716fa4e4ada65306f688 この記事について質問です。 投稿自体初めてなので見にくいかもしれませんがすみません。

コード自体は元のものに自分の環境で動作するように多少書き換えました。

from pixivpy3 import *
import json
import os
from PIL import Image
import glob
from time import sleep


#ここは各個人にやってもらう設定です

#一人当たりダウンロードする作品の最大数、すべてダウンロードしたい場合はできるだけ大きくすること    (一人の作者の作品数を超えること)
#新しい順にダウンロードされます
works=9999999999999999999999999999999
#ブックマーク数によるフィルター、最小値を設定、0ならすべて
score=100
    #閲覧数によるフィルター、最小値を設定、0ならすべて
view=0

#タグによるフィルター 書き方 target_tag = ["Fate/GrandOrder","FGO","FateGO","Fate/staynight"]
target_tag = [] #target_tag内に複数書くと、そのうち少なくとも一つあればダウンロード
target_tag2 = []#さらにtarget_tag2に書くとtarget_tagを満たし、かつtarget_tag2を満たすものだけダウンロード
extag = [""]#extag内のタグが一つでも入っていればダウンロードしない

#画像を保存するディレクトリ
main_saving_direcory_path = "./img/"



#事前処理

#事前に作ったアカウント情報が書かれたファイルを読み込む
with open("client.json", "r") as f:
client_info = json.load(f)

# pixivpyのログイン処理
api = PixivAPI()
api.login(client_info["pixiv_id"], client_info["password"])
aapi = AppPixivAPI()
aapi.login(client_info["pixiv_id"], client_info["password"])




#ここからダウンロードについて
def downloader(id_search):
#ユーザーのデータをとってくる前のsleep
sleep(1)

#入力されたidの作品数を取得
illustrator_id = api.users_works(id_search, per_page=works)


#アカウントだけで絵が投稿されていない人を避けるため
if not illustrator_id.count == 0:
    total_works = illustrator_id.pagination.total
    if works < total_works:
        total_works=works

    #ユーザーの情報を得るために最初の作品のデータをとってくる
    illust = illustrator_id.response[0]

    #user名でフォルダを作るため、windowsのフォルダ名に使えない文字を置換
    username = illust.user.name.translate(str.maketrans({'/': '_' , ':': ':', ',': '_', ';': ';' ,'*': '_', '?': '?', '"': "'", '>': ')', '<': '(', '|': '|'}))
    username = username.rstrip(".")
    username = username.lstrip(".")
    username = username.rstrip(" ")
    username = username.rstrip(" ")

    #ユーザー名(id)の形でフォルダを作成

    saving_direcory_path = main_saving_direcory_path + username + ("(") +str(illust.user.id) + (")") + "/"

    #フォルダ名を最新のユーザー名に直す
    saving_direcory_name = saving_direcory_path[:-1]
    present_folder_list = glob.glob(main_saving_direcory_path + "*")

    for present_dir in present_folder_list:
        num = present_dir.rsplit("(", 1)[-1][:-1]
        #print(num)
        name = present_dir.rsplit("\\", 1)[-1]
        name = name.rsplit("(", 1)[0]
        #print(name)
        #print("--------------------------------------")
        if num == str(illust.user.id) and username != name:
            print(present_dir + "を次に変更" + saving_direcory_name)
            print("--------------------------------------")
            os.rename(present_dir, saving_direcory_name)





    #フォルダが存在しないときは作る
    if not os.path.exists(saving_direcory_path):
        os.mkdir(saving_direcory_path)
    separator = "------------------------------------------------------------"

    #Display information of illustrator and the number of illustrations
    print("Illustrator: {}".format(illust.user.name))
    print("Works number: {}".format(illustrator_id.pagination.total))
    print(separator)




    #Download
    for work_no in range(0, total_works):
        illust = illustrator_id.response[work_no]

        #フィルター

        #タグによるフィルター
        if len(list(set(target_tag)&set(illust.tags))) == 0 and target_tag != []:
            continue
        if len(list(set(target_tag2)&set(illust.tags))) == 0 and target_tag2 != []:
            continue
        #exタグが一つでも入っていたらスキップ
        if len(list(set(extag)&set(illust.tags))) > 0 :
            continue
        #score以上の作品だけダウンロード
        if illust.stats.favorited_count.private + illust.stats.favorited_count.public < score :
            continue
        #view以上の作品だけダウンロード
        if illust.stats.views_count < view :
            continue



        #if the illustration has already downloaded, skip downloading it
        #pixivに投稿できるのはpng,jpg,gif,うごイラ
        #ここではあくまで1ページ目がダウンロードされているかで判断しているので、ダウンロード中に通信が途切れ、2ページ目以降がダウンロードされていないかはわからない

        if os.path.exists(saving_direcory_path+str(illust.id)+"_p0.png") or os.path.exists(saving_direcory_path+str(illust.id)+"_p0.jpg") or os.path.exists(saving_direcory_path+str(illust.id)+'_ugoira') or os.path.exists(saving_direcory_path+str(illust.id)+"_p0.gif"):
            print("Title:"+str(illust.title)+" has already downloaded.")
            print(separator)
            continue

        #ダウンロード前のスリープ
        sleep(1)
        print("Now: {0}/{1}".format(work_no + 1, total_works))
        print("Title: {}".format(illust.title))


        #うごイラ
        if illust.type == "ugoira":
        #イラストIDの入力待機
            illust_id = illust.id
            ugoira_url = aapi.illust_detail(illust_id).illust.meta_single_page.original_image_url.rsplit('0', 1)
            ugoira = aapi.ugoira_metadata(illust_id)
            ugoira_frames = len(ugoira.ugoira_metadata.frames)
            ugoira_delay = ugoira.ugoira_metadata.frames[0].delay
            dir_name = saving_direcory_path + str(illust_id)+'_ugoira'


            #うごイラを保存するフォルダの作成
            if not os.path.isdir(dir_name):
                os.mkdir(dir_name)

            #うごイラに使われているすべての画像のダウンロード
            for frame in range(ugoira_frames):
                frame_url = ugoira_url[0] + str(frame) + ugoira_url[1]
                aapi.download(frame_url, path=dir_name)


            #保存した画像をもとにgifを作成
            #力不足でgifにする際に結構画像が劣化します
            #pythonでgif作成のライブラリを探しましたが、圧縮度合いを設定できるものが見つかりませんでした。
            frames = glob.glob(f'{dir_name}/*')
            frames.sort(key=os.path.getmtime, reverse=False)
            ims = []
            for frame in frames:
                ims.append(Image.open(frame))
            ims[0].save(f'{dir_name}/{illust_id}.gif', save_all=True, append_images=ims[1:], optimize=False, duration=ugoira_delay, loop=0)

        # illustrations with more than one picture
        elif illust.is_manga:
            work_info = api.works(illust.id)
            for page_no in range(0, work_info.response[0].page_count):
                page_info = work_info.response[0].metadata.pages[page_no]
                aapi.download(page_info.image_urls.large, saving_direcory_path)

        # illustrations with only one picture
        else:
            aapi.download(illust.image_urls.large, saving_direcory_path)

        print(separator)


    print("Download complete! Thanks to {0}{1}!!".format(illust.user.id, illust.user.name))


followids = client_info["ids"]

for id_search in followids:
try:
    downloader(id_search)
except:
    print("erro")

このコードを実行すると添付画像のようにerrorが発生し、その後のctrl+cやescの停止コマンドを受け付けないため手動で強制終了し再起動しなければならないという状況です。
スクリーンショット a2021-01-09 150236.jpg
原因として、有線で実行しているためネット環境の問題ではなくまた再実行した際は当該箇所以降も問題なく作動しまたある程度進むと停止するという状況で製作者さんも不明だそうです。
sleepの時間を10にするなども試しました。

この問題解決方法を教えていただきたいです。
それが難しければプログラムの自己再起動コマンドを教えていただきたいです。

蛇足ですが、当該urのIDgetterもなぜか5010個のID以上取得できないのでその解決策も知りたいです。

0

2Answer

This answer has been deleted for violation of our Terms of Service.

for id_search in followids:
try:
    downloader(id_search)
except:
    print("erro")

for id_search in followids:
    downloader(id_search)

でどうですか

0Like

Comments

  1. @fukubucho_

    Questioner

    そうするとなぜか途中の小さなerror1つで勝手に終了してしまうんですよね
    なので可能であればエラーが20回出たら最初からコマンドを打ち直してダウンロードを始めるという方法が最も手堅いと思って自分なりにやってみたのですがそれも上手くいかない状況で…
  2. @fukubucho_

    Questioner

    @yuki_2020 さん、タイムスケジューラによる自動化のために起動からエラーまでの時間を測ってみたのですがピッタリ60分でエラーが発生することが分かりました。
    これはやはりPixivpyの方の問題なのでしょうか?
  3. おそらくpixivのサーバー側が60分間一定の間隔でアクセスするのを不正アクセスもしくはサーバーに負荷をかける行為だと認識して通信を切断しているのではないでしょうか
  4. @fukubucho_

    Questioner

    ダウンロードに関してはダウンロード済みIDをjsonファイルから消していくことと一時間おきにタイムスケジューラを実行することで着実にダウンロードできるようになりました!
    ただ、唯一残った問題として、6600フォローに対して5010までしかIDを取れないのですが、今のIDgetterは新しい順に取得していますが逆に古い順で取得することはできないでしょうか?
    そうすれば最大10040フォローまで対応できるようになると思うのですが

Your answer might help someone💌