『なろう小説API』を用いて、なろうの『全作品情報データを一括取得する』Pythonスクリプト※コード改良しました
pythonを使ってなろうの全ての情報を取得する
なろうが提供する「なろう小説API」を用いて、なろうに存在するすべての小説情報データを全件取得するコードです。
とりあず手元になろうの全件データセットを持った上で解析を行いたい人向けの「全部をすべて取得するPythonコード」です。
なろう小説APIで取得できる全作品情報データの全40項目を一括取得できます。(2021年1月現在約86万件分)
取得データについては、「なろうディベロッパー」サイトを御覧ください。
https://dev.syosetu.com/man/api/:なろう小説API(なろうディベロッパー)
このスクリプトを使うことで「ポチポチ」で全件取得が可能となります。
Githubのページ
使用準備
以下のパッケージを使用していますのでインストールしていない場合はインストールしてご利用ください。
pip install pandas
pip install tqdm
pip install requests
追加:2019/9/29
pip install xlsxwriter
使用方法の説明
pythonを使って、なろうAPIからすべての小説情報データを引っ張ってきて、一つの.xlsx(エクセル形式)ファイルで出力するスクリプトです。
約半日動かせば、なろうのすべてが取得できます。コードの改良で約90分で全取得できるようなりました。
使用方法
Anacondaのjupyter notebookやPython3.5で.pyを実行してください。
実行ファイルと同じフォルダに
#出力ファイル名
filename ='All_OUTPUT.xlsx'
で指定したエクセルファイルが出力されます。約200MB。
取得項目
なろう小説APIで取得できる全40項目を取得します。
title
ncode
userid
writer
story
biggenre
genre
gensaku
keyword
general_firstup
general_lastup
novel_type
end
general_all_no
length
time
isstop
isr15
isbl
isgl
iszankoku
istensei
istenni
pc_or_k
global_point
daily_point
weekly_point
monthly_point
quarter_point
yearly_point
fav_novel_cnt
impression_cnt
review_cnt
all_point
all_hyoka_cnt
sasie_cnt
kaiwaritu
novelupdated_at
updated_at
weekly_unique
※2019.8.20より追加
daily_point
weekly_point
monthly_point
quarter_point
yearly_point
impression_cnt
トラブルシューティング
「pandas」が見つからないというエラーが出る。
pip install pandas
このスクリプトでは「pandasパッケージ」を使っています。なのでpipからpandasをインストールしてください。
anacondaの場合は、スタートメニューのなかにあるanaconda promptで実行し、jupyter notebookを再起動してください。
取れないデータがある。数が合わない
なぜか落とせないデータはあるみたいです。
落とせないデータについてはpassする様に設定しています。
※コードの改良で完全に全部取得できるようになりました
エクセルで開くとエラーが出る
何件かのデータがバッグっているのでデータを初めて読み込んだ時は「修復しますか?」とダイアログが出るので「修復する」を選択して下さい。
エクセルで開けないほど重い
エクセルで扱えないというほど大きいファイルサイズではないですが、ゴリゴリ解析していくのには時間がかかります。
ピポットデーブルで作業する場合は、作業用に必要な列だけ抜き出したシートを用意して行ったほうが効率的です。
本格的な解析はpythonみたいなプログラミングソフトで行った方が効率的です。
全件取得スクリプト
#『なろう小説API』を用いて、なろうの『全作品情報データを一括取得する』Pythonスクリプト #2020-04-26更新 import requests import pandas as pd import json import time as tm import datetime import gzip from tqdm import tqdm tqdm.pandas() import xlsxwriter import sqlite3 #リクエストの秒数間隔(1以上を推奨) interval = 2 ### なろう小説API・なろう18禁小説API を設定 #### is_narou = True now_day = datetime.datetime.now() now_day = now_day.strftime("%Y_%m_%d") if is_narou: filename = 'Narou_All_OUTPUT_%s.xlsx'%now_day sql_filename = 'Narou_All_OUTPUT_%s.sqlite3'%now_day api_url="https://api.syosetu.com/novelapi/api/" else: filename ='Narou_18_ALL_OUTPUT_%s.xlsx'%now_day sql_filename = 'Narou_18_ALL_OUTPUT_%s.sqlite3'%now_day api_url="https://api.syosetu.com/novel18api/api/" # データをSqlite3形式でも保存する is_save_sqlite = False ##### 以上設定、以下関数 ############## #全作品情報の取得 def get_all_novel_info(): df = pd.DataFrame() payload = {'out': 'json','gzip':5,'of':'n','lim':1} res = requests.get(api_url, params=payload).content r = gzip.decompress(res).decode("utf-8") allcount = json.loads(r)[0]["allcount"] print('対象作品数 ',allcount); all_queue_cnt = (allcount // 500) + 10 #現在時刻を取得 nowtime = datetime.datetime.now().timestamp() lastup = int(nowtime) for i in tqdm(range(all_queue_cnt)): payload = {'out': 'json','gzip':5,'opt':'weekly','lim':500,'lastup':"1073779200-"+str(lastup)} # なろうAPIにリクエスト cnt=0 while cnt < 5: try: res = requests.get(api_url, params=payload, timeout=30).content break except: print("Connection Error") cnt = cnt + 1 tm.sleep(120) #接続エラーの場合、120秒後に再リクエストする r = gzip.decompress(res).decode("utf-8") # pandasのデータフレームに追加する処理 df_temp = pd.read_json(r) df_temp = df_temp.drop(0) df = pd.concat([df, df_temp]) last_general_lastup = df.iloc[-1]["general_lastup"] lastup = datetime.datetime.strptime(last_general_lastup, "%Y-%m-%d %H:%M:%S").timestamp() lastup = int(lastup) #取得間隔を空ける tm.sleep(interval) dump_to_excel(df) #エクセルファイルに書き込む処理 def dump_to_excel(df): # allcount列を削除 df = df.drop("allcount", axis=1) # 重複行を削除する df.drop_duplicates(subset='ncode', inplace=True) df = df.reset_index(drop=True) print("export_start",datetime.datetime.now()) try: # .xlsx ファイル出力 writer = pd.ExcelWriter(filename,options={'strings_to_urls': False}, engine='xlsxwriter') df.to_excel(writer, sheet_name="Sheet1")#Writerを通して書き込み writer.close() print('取得成功数 ',len(df)); except: pass ### SQLite3に書き込む処理 (将来エクセルの上限行数を超えたときのため) ### if is_save_sqlite == True or len(df) >= 1048576: # 接続DBファイルの指定 conn = sqlite3.connect(sql_filename) conn.row_factory = sqlite3.Row c = conn.cursor() df.to_sql('novel_data', conn, if_exists='replace') c.close() conn.close() print("Sqlite3形式でデータを保存しました") ####### 関数の実行を指定 ########## print("start",datetime.datetime.now()) get_all_novel_info() print("end",datetime.datetime.now())
追記:「なろう18禁小説API」全取得コードもアップしました!
karupoimou.hatenablog.com
なろう18禁小説APIむけのコードも作成しましたのでもしご興味ありましたらご覧ください。
資料
Anacondaやpythonの基本は上記の記事をご参照ください。
Jupyter Notebookの設定は上記の記事をご参照ください。
python3.7の環境を使う際にはご参照ください。
また定期的に自動実行するときなどには上記の記事をご参照ください。