こんにちは。
先日ふと、pixiv小説をデータセットに使いたいと思いクローラーを作れないかなと思って作ってみました。
apiはtwo/pixiv.pyを利用します。
リポジトリをクローンしたのち作業はpixiv/で行います。
プログラムは指定したidから順番に1つづつ減らしていって取得しています。
- id
- 本文
- タグ
をsqliteに突っ込んでます。
errorが帰ってきたらerror文をみてapi制限エラーだったらsleepするようにしてます。
以下コードです。
crawl.py
# -*- coding: utf-8 -*-
from pixiv.auth import OAuthHandler
from pixiv.api import PixivAPI, AppPixivAPI
from pixiv.cursor import Cursor, AppCursor
from pixiv.utils import PixivDownload
import sys
import sqlite3
import time
import json
auth = OAuthHandler()
auth.login('id', 'pass')
aapi = AppPixivAPI(auth)
con = sqlite3.connect("novel.db")
cur = con.cursor()
cur.execute("""CREATE TABLE IF NOT EXISTS Novel(id int PRIMARY KEY,tag varchar(10000), text varchar(10000));""")
cnt=200000
while(True):
try:
novel=aapi.novel_text(novel_id=cnt)
tagstr=''
try:
series_prev=novel.series_prev.id
sprev=aapi.novel_text(novel_id=int(series_prev))
for tag in sprev.series_next.tags:
tagstr+=tag['name']+','
except:
pass
try:
series_next=novel.series_next.id
snext=aapi.novel_text(novel_id=int(series_next))
for tag in snext.series_prev.tags:
tagstr+=tag['name']+','
except:
pass
if(tagstr==''):
cnt-=1
continue
con.execute("insert or replace INTO Novel VALUES(?,?,?)", (cnt,tagstr,novel.novel_text))
sys.stdout.write("\r%d Download." % cnt)
sys.stdout.flush()
con.commit()
cnt-=1
except Exception as e:
try:
if('該当作品は削除されたか、存在しない作品IDです。'==str(e.args[0]['error']['user_message']) or '該当作品の公開レベルにより閲覧できません。'==str(e.args[0]['error']['user_message'])or '公開制限エラーです。'==str(e.args[0]['error']['user_message'])):
sys.stdout.write("\r%d Download." % cnt)
sys.stdout.flush()
cnt-=1
continue
elif('閲覧制限エラーです。'==str(e.args[0]['error']['user_message'])):
novel=aapi.search_novel(word=str(cnt))[0]
id=str(novel.id)
tagstr=''
for tag in novel.tags:
tagstr+=tag['name']+','
con.execute("insert or replace INTO Novel VALUES(?,?,?)", (cnt,tagstr,aapi.novel_text(novel_id=id).novel_text))
sys.stdout.write("\r%d Download." % cnt)
sys.stdout.flush()
con.commit()
cnt-=1
continue
elif('Rate Limit'==str(e.args[0]['error']['message'])):
print('sleep600')
time.sleep(600)
except Exception as e2:
print(e2.args)
print(e.args)
cnt-=1