Pythonで行う「なろう小説API」の分析 コード例、環境準備、トラブルシューティング
なろう小説APIを使って『小説家になろう』を分析する
小説家になろうでは作品情報を扱うことができるAPIが提供されているため、それを利用することでさまざまなデータを簡単に得ることが出来ます。
ここでは、Pythonを使ってそれらを落としてくる方法を解説します。
手っ取り早くコピペコードでなろうデータを全取得したい人はこちら
『なろう小説API』を用いて、なろうの『全作品情報データを一括取得する』Pythonスクリプト※コード改良しました - なろう分析記録
Pythonを使う環境の準備
windowsユーザ向け
Anacondaの「jupyter notebook」を使うのが簡単。普通に日本語で使えます。
インストーラの説明に従ってインストールすれば完了。
必要なパッケージは全部入っている。
より快適に使う設定は下記の記事をご参照ください。
コード編
最もシンプルなコード
import requests import yaml payload = {'out': 'yaml'} r = requests.get('https://api.syosetu.com/novelapi/api/', params=payload).text print(r)
ポイント上限とポイント下限を指定
import requests import yaml payload = {'out': 'yaml','min_globalpoint':38,'max_globalpoint':50} r = requests.get('https://api.syosetu.com/novelapi/api/', params=payload).text print(r)
表示件数を500に
import requests import yaml payload = {'out': 'yaml','lim:500} r = requests.get('https://api.syosetu.com/novelapi/api/', params=payload).text print(r)
ジャンル別の総作品数を表示
import requests import yaml import time genre_set = ['101','102','201','202','301','302','303','304','305','306','307','401','402','403','404','9901','9802','9903','9904','9999','9801'] for genre in genre_set: payload = {'out': 'yaml','st':1,'lim':1,'of':'g','genre':genre} r = requests.get('https://api.syosetu.com/novelapi/api/', params=payload).text with open("output_genre_num001.yaml","a") as file: yaml.dump(r, file, default_flow_style=False,allow_unicode=True) time.sleep(1) print(r) print("end")
ここではfor文で繰り返し実行することで可能に。 output_genre_num001.yamlに順に書き込んでいく。
短編・連載の作品数 を出すだけのコード
import requests import yaml import time shousetu_type_set =['t','re'] for shousetu_type in shousetu_type_set: payload = {'out': 'yaml','st':1,'lim':1,'of':'n','type':shousetu_type} r = requests.get('https://api.syosetu.com/novelapi/api/', params=payload).text time.sleep(1) print(r) print("end")
typeによって区別。
YAMLロードする用のコード
import yaml f = open("output_genre_num001.yaml", "r+") data = yaml.safe_load(f) print(data) print("end")
output_genre_num001.yamlを読み出して表示。
なお「yaml.load()」を使うとエラーがでるので、「safe_load()」にしている。
特定作者の作品一覧を表示
#作者分析 高ポイント順ソートしてテキスト出力するPythonスクリプト import requests import yaml import time import webbrowser import datetime now = datetime.datetime.now() #出力ファイル名の指定。接頭語+日時 t = 'mine_{0:%Y%m%d}.txt'.format(now) #test_20170910 #時刻の書き込み dt_now = datetime.datetime.now() nowtime = dt_now.strftime('%Y-%m-%d %H:%M:%S') with open(t,mode='w',encoding='utf-8') as f: f.write(nowtime) #ここに作者ユーザーIDをコピペ userid = ['511777'] #新着更新順にする場合は 'new' 新着投稿順にする場合は 'ncodedesc' order_set = ['hyoka'] #なろう小説APIへリクエスト payload_simple = {'out': 'yaml','lim':500,'order':order_set,'userid':userid,'of':'n-t-gp-f-ah-a'} r1 = requests.get('https://api.syosetu.com/novelapi/api/', params=payload_simple).text time.sleep(0.1) payload_all = {'out': 'yaml','lim':500,'order':order_set,'userid':userid,'of':'t-n-s-g-k-gf-gl-ga-l-gp-f-r-a-ah'} r2 = requests.get('https://api.syosetu.com/novelapi/api/', params=payload_all).text #書き込みテキストファイルの指定 with open(t,mode='a',encoding='utf-8') as f: f.write(r1) f.write(r2) #完了時にファイルを自動で開く設定(必要なければ消して良い) webbrowser.open(t) print("end") # 詳しくは なろうデベロッパー # https://dev.syosetu.com/man/api/ をご参照あれ
作者IDは作者マイページに行けば分かる。
例:
https://mypage.syosetu.com/511777/
エクセル読み出し
import requests import yaml import time import xlrd import pprint #読み込みファイル指定 wb = xlrd.open_workbook('word.xlsx') #シート指定 列指定 sheets = wb.sheets() sheet = wb.sheet_by_name('sheet1') word_set = sheet.col_values(0) # ポイント数 max_globalpoint_set = ['1','101','1001','1000000000000'] for word in word_set: for max_globalpoint in max_globalpoint_set: payload = {'out': 'yaml','st':1,'lim':1,'of':'n','max_globalpoint':max_globalpoint,'word':word,'title':0,'ex':0,'keyword':1} r = requests.get('https://api.syosetu.com/novelapi/api/', params=payload).text with open("output_genre_num001.yaml","a") as file: yaml.dump(r, file, default_flow_style=False,allow_unicode=True) print(word) print(r) time.sleep(0.05) print("end")
word.xlsxのsheet1の一列目にある文字を使って、全部解析して、output_genre_num001.yamlに書き込み。
説明が面倒なので実際試してみて下さい。
部品別の説明
結果をテキストファイルに書き込み
import requests import yaml payload = {'out': 'yaml'} r = requests.get('https://api.syosetu.com/novelapi/api/', params=payload).text print(r) with open('test001.txt',mode='w',encoding='utf-8') as f: f.write(r)
なおmodeを指定することで、追記か、新規作成か選べる。詳細は下に
テキストの「追記」と「完全上書き」
with open('test001.txt',mode='w',encoding='utf-8') as f:
のばあいの「mode='w'」というところで指定している。
w = 上書き もしファイルが無ければ生成。ファイルの初期化にも使う。
a = 追記用
テキストファイルに時間を書き込む
import datetime dt_now = datetime.datetime.now() t = dt_now.strftime('%Y-%m-%d %H:%M:%S') with open('test001.txt',mode='w',encoding='utf-8') as f: f.write(t) print(t)
リクエストを始めた時間とか終えた時間のメモに使うとよい。
ファイル名に日時を使う
##時刻を文字に置き換える import datetime now = datetime.datetime.now() t = 'mine_{0:%Y%m%d}.txt'.format(now) #test_20170910 #書き込みテキストファイルの指定 with open(t,mode='w',encoding='utf-8') as f: f.write("test") print(t)
完了の表示
print("end")
これをコードの末尾に加えておくとよい。
完了時にファイルを自動で開く設定
import requests import yaml import time import webbrowser payload_simple = {'out': 'yaml'} r = requests.get('https://api.syosetu.com/rank/rankget/', params=payload_simple).text #書き込みテキストファイルの指定 with open('00003.txt',mode='w',encoding='utf-8') as f: f.write(r) print(r) #完了時にファイルを自動で開く設定 webbrowser.open('00003.txt')
webbrowserを使って表示を実現。
辞書型データからのデータの取り出し
import requests import yaml payload = {'out': 'yaml'} r = requests.get('https://api.syosetu.com/novelapi/api/', params=payload).text for data in yaml.safe_load(r): try: title = data['title'] print(title) except KeyError: pass
for文を使って、辞書型データから情報を取り出している。
これを使うことによって、CSVとかに書き込める。
ジャンル別の作品数を出すコード
#ジャンルごとの作品数を表示 import requests import yaml import gzip genre_set = ['101','102','201','202','301','302','303','304','305','306','307','401','402','403','404','9901','9902','9903','9904','9801','9999'] def dump_to_list(r): for data in json.loads(r): try: print(data['allcount']) except KeyError: pass for gen in genre_set: payload = {'out': 'json','gzip':5,'of':'n','lim':1,'genre':gen} res = requests.get('https://api.syosetu.com/novelapi/api/', params=payload).content r = gzip.decompress(res).decode("utf-8") print(gen," ", end="") dump_to_list(r); print("end")
sys関数
pythonの実行環境を表示する
import sys print(sys.version) #>>3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
このコードはpythonをレンタルサーバーなどで実行する際などに便利です。
import sys print(sys.path) #>>['C:\\ProgramData\\Anaconda3\\python36.zip', 'C:\\ProgramData\\Anaconda3\\DLLs', 'C:\\ProgramData\\Anaconda3\\lib', 'C:\\ProgramData\\Anaconda3', '', 'C:\\ProgramData\\Anaconda3\\lib\\site-packages', 'C:\\ProgramData\\Anaconda3\\lib\\site-packages\\win32', 'C:\\ProgramData\\Anaconda3\\lib\\site-packages\\win32\\lib', 'C:\\ProgramData\\Anaconda3\\lib\\site-packages\\Pythonwin', 'C:\\ProgramData\\Anaconda3\\lib\\site-packages\\IPython\\extensions', 'C:\\Users\\ユーザー名\\.ipython']
このコードも、どの様にpythonのパスが通っているのか調べるために便利です。
同ディレクトリ内に存在するファイル名をリストオブジェクトとして取得
import glob filename=glob.glob("./*") print(filename) #>>['.\\jinja2_test.html', '.\\jinja2_test.ipynb', '.\\jinja2_test.py', '.\\jinja2_test.txt']
トラブルシューティング
jupyter notebookが立ち上がらない
コンソール画面を右クリックして「全選択」→「コピー」をしてから、それをwordとかに入りつけれから、URLをクリックすればよい。
コンソールが閉じてしまうのは、ctlr+Cボタンを押しているから。それすると落ちる。
anaconda 立ち上げる度に毎回 anaconda nvigerter アップデートしろとうるさい
全データを一括取得するコード
とりあえず全件取得してから、手元にデータを置いた状態で分析をしたい。という方は以下のコードをご利用下さい。
半日ほどで約200MBの全件データが手に入ります。特に設定の必要はありませんのでポチポチで実行できます。