旭駅本屋

SNSが普及しきった今日において、人々はなぜブログを使うのであろうか。

RSS

 

pixivから任意のイラストレーターさん方のイラストを無限に取得したかった

pixivのapiは公開されていないものの、有志がpixivpyといういい感じにapiを叩いてくれるライブラリを公開しているので、今回はそれを利用してタイトルどおりのことをします。

とはいえ、基本的にはこことやってることは変わらないです。はい。

 

今回自分の要件としては、

・手元にあるイラストは除外する(鯖の負担軽減も兼ねて)

・フォローユーザーを一斉クロールも可能ではあるものの、当面User IDは別ファイルで流す

 

というところがあったので、それが出来るように先述のところのコードをぼちぼち変えていきました。

 

事前準備

必要なライブラリを用意します。そもそもPythonが入っていない人は入れましょう。ちなみに筆者はpython3.7で動かしているので2系入れるとまず動かないと思います。

Pythonを入れたら環境変数をいい感じにして、cmdからpythonとpipを叩けるようにします。多分このへんはググれば出てくると思うので探してください。

そこまでできたら、pipで必要なライブラリをインストールします。

pip install pixivpy
pip install beautifulsoup4
pip install robobrowser
pip install lxml

 

ファイル構成

E:crawl

├─artist.csv
├─client.json
├─get-illustrations.py
├─file_list.txt
└─file_replace.py

こんな感じです。作業用のフォルダは適当に読み替えてください。file_replaceくんはfile_listくんを整形するためだけに使っているので今回は特に説明はしません。基本dirで出した結果からイラストレーター名とファイル名のcsvにしているだけなので、まあ今回の要旨ではないでしょう。

 

以下、スクリプト絡みのファイルをざっと流していきます。

 

get-illustrations.py

# -*- coding: utf-8 -*-

import sys
from pixivpy3 import *
import json
from time import sleep
import os
import codecs
import re

 

# 変更するときはここをいじろう
saving_current_direcory = "E:\\二次絵保管庫\\"
account_json = "E:\\crawl\\client.json"
file_list_csv = "E:\\crawl\\file_list.txt"
artist_csv = "E:\\crawl\\artist.csv"

 
api = PixivAPI()
f = open(account_json, "r")
client_info = json.load(f)
f.close()

 

# file_list.txtを取得

    # Windowsくんが無能なのでSjisですが、適当に変えてください。
f = codecs.open(file_list_csv,"r","shift_jisx0213")
file_info = f.read().split("\r\n")
f.close
file_list = []
for line in file_info:
    if line != "":
        file_list.append(int(re.sub("_p\d+.(jpg|png|jpeg|gif)$","",line)))

file_list = list(set(file_list))
del file_info

# artist.csvを取得
f = codecs.open(artist.csv,"r","utf-8")
artist_info = f.read().split("\r\n")
f.close()
artist_list = []
for line in artist_info:

    if line != "":
        artist_list.append(line.split(","))

del artist_info

 

# 入力されたuserIDからイラストレーターの情報を取得
for artist in artist_list:
    # ログイン処理
    api.login(client_info["pixiv_id"], client_info["password"])


    illustrator_pixiv_id = int(artist[0])

    try:

        json_result = api.users_works(illustrator_pixiv_id, per_page=1000) # とりあえずmax1000作品と定義
        total_works = json_result.pagination.total
        illust = json_result.response[0]
        saving_direcory_path = saving_current_direcory + artist[1] + "\\"
        aapi = AppPixivAPI()

        # ダウンロード
        if not os.path.exists(saving_direcory_path):
            os.mkdir(saving_direcory_path)

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

                if int(illust.id) not in file_list:
                    # 漫画の場合
                    if 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)
                            sleep(10)
                        # イラストの場合
                        else:
                            aapi.download(illust.image_urls.large, saving_direcory_path)
                            sleep(10)

    except:
        print("ERROR from "+artist[1])
        sleep(600)
    print(artist[1] + " fin")
    sleep(60)

 

ここが本体です。いい感じに用意しておくと本当にいい感じに採ってきてくれます。優秀です。例外処理が皆無なことを除けば。 追加しました。エスケープ文字を適切に置換すると動くと思います。動かなければ@ichikawa_ykhmにクソリプ飛ばしてください。ソース返します。

テキストデータ上げました→ 

http://ithikawa.sakura.ne.jp/get-illustrations.txt

 

 

client.json

{
    "pixiv_id": <pixiv_id>,
    "password": <password>,
    "user_id": <user_id>
}

基本的に上にあるQiitaの記事と同じです。

 

file_list.txt

<file_name>

ここのfile_nameは基本的に拡大画像をそのまま取得した場合と同じパスです。つまるところ<Illustrator_id>_p0.jpgみたいなのです。

 

artist.csv

<user_id>,<name>

持ってきたい絵描きさんのuser ID、名前を入れると、Pixivからいい感じに持ってきて名前と同じ名前のフォルダにブチ込まれます。そういう仕様のソースになってます。 

 

とまあ、こんな感じに仕立てて動かすといい感じになってくれて、いちいちchromeのタブをポチポチしながら人力クロールする必要もなくなるわけです。やったね!

ちなみに、なんでかあんまりilust_idの除外は判定しきれていないっぽい。かなしい。普通に型判定ミスってただけでした。