RCれこーど

プログラミングについて勉強したことや行ったこと,その他気になったことを記録するブログ(予定)

APIの知識ゼロからPythonでWebAPIを叩いてみる【なろう小説API】

今までAPIというものを使ったことがなかったので,PythonAPIを使ってデータを取得することを試みてみようと思います.
今回使用するAPIは,小説家になろうに掲載されている小説の情報が取得できる,なろう小説APIです.

なろう小説API

PythonAPIを利用する方法

使い方を調べる

とりあえず,PythonAPIを利用する方法が分からなかったのでググってみたところ,シンプルに使用方法を説明してくださっている記事を発見しました.この記事を参考にさせて頂こうと思います.

tabilike.hatenablog.com

urllib3というライブラリを使うのが良いそうです.
というわけでインストールします.

pip install urllib3

接続する

先ほどの記事に従い,とりあえずなろう小説APIのページにAPIのURLと書かれているURLをそのまま入れて実行してみます.

APIのURL
https://api.syosetu.com/novelapi/api/
GETで送信。POSTでは受信できません。
日本語などマルチバイト文字送信時は文字コードUTF-8にし、URLエンコードしてください。

import urllib3
r = http.request('GET','https://api.syosetu.com/novelapi/api/')

実行結果

NameError: name 'http' is not defined

エラーが出て失敗してしまいました.
そこで公式っぽいドキュメントを見たところ,このように書かれていました.

>>> import urllib3
>>> http = urllib3.PoolManager()
>>> r = http.request('GET', 'http://httpbin.org/robots.txt')
>>> r.status
200
>>> r.data
'User-agent: *\nDisallow: /deny\n'

urllib3 — urllib3 dev documentation
こちらも参考に,コードを書き換えて実行します.

import urllib3
http = urllib3.PoolManager()
r = http.request('GET','https://api.syosetu.com/novelapi/api/')

実行結果

InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning)

すると安全ではないよ,というような警告が出ましたが,今回は試すだけなのでひとまず置いておくことにします.

繋がったかの確認

次は繋がったかの確認を行います.

r.status

実行結果

200

この数字はHTTPステータスコードというものっぽいです.200の場合は成功のようです.

2xx Success 成功 リクエストは受け取られ、理解され、受理された。

200 OK
OK。リクエストは成功し、レスポンスとともに要求に応じた情報が返される。
ブラウザでページが正しく表示された場合は、ほとんどがこのステータスコードを返している。
HTTPステータスコード - Wikipedia

データの中を確認

次はデータの中身を見てみます.

r.data

実行結果 (とても長かったので一部だけ記載)

b'---\n- \n allcount: 563448\n- \n title: >\n \xe7\x95\xb0\xe4\xb8\x96\xe7\x95\x8c\xe3\x81\xab\xe6\x9d\xa5\xe3\x81\x9f\xe3\x81\xbf\xe3\x81\x9f\xe3\x81\x84\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xa9\xe5\xa6\x82\xe4\xbd\x95\xe3\x81\x99\xe3\x82\x8c\xe3\x81\xb0\xe8\x89\xaf\xe3\x81\x84\xe3\x81\xae\xe3\x81\xa0\xe3\x82\x8d\xe3\x81\x86\n ncode: N0885DC\n userid: 615833\n writer: \xe8\x88\x9e\n story: |\n 35\xe6\xad\xb3\xe3\x83\xa1\xe3\x82\xbf\xe3\x83\x9c\xe3\x81\xae\xe3\x82\xb5\xe3\x83\xa9\xe3\x83\xaa\xe3\x83\xbc\xe3\x83\x9e\xe3\x83\xb3\xe3\x81\x8c\xe3\x81\x82\xe3\x82\x8b\xe6\x9c\x9d\xe5\x94\x90\xe7\xaa\x81\xe3\x81\xab\xe7\x95\xb0\xe4\xb8\x96\xe7\x95\x8c\xe3\x81\xab\xe9\xa3\x9b\xe3\x81\xb0\xe3\x81\x95\xe3\x82\x8c\xe3\x81\x9f\xe3\x80\x82\n

長くてよく分からない文字の羅列ですが,とにかくAPIからデータを得ることができました.

データの中身の詳細となろう小説APIの利用方法(少々)

得られたよく分からない羅列ですが,なろう小説APIの説明によるとYAML形式というものだそうです.パラメータを変えることによって他の形式にも変更できるようです.

・出力形式
JSON形式、JSONP形式またはYAML形式、PHPのserialize
標準はYAML形式となっていますが、outパラメータで変更できます。
文字コードUTF-8です。

そこで,実際によく聞くことがあるJSON形式で取得してみようと思います.

JSON形式で取得してみる

パラメータを変える方法は,APIのURLに設定を付け足して行うようです.
「?」の後に「out=json」を付け足し,outパラメータをjsonと設定します.

https://api.syosetu.com/novelapi/api/?out=json

先ほどのソースコードURLをこのURLにしてデータを確認してみます.

import urllib3
http = urllib3.PoolManager()
r = http.request('GET','https://api.syosetu.com/novelapi/api/?out=json')
r.data

ところで,参考にさせて頂いてる記事によると,このような書き方が可能なようです.

r = http.request('GET','https://api.syosetu.com/novelapi/api',fields={'out': 'json'})

実行結果(一部)

b'[{"allcount":563448},{"title":"\u9b3c\u4eba\u751f\u5f92\u306e\u30cf\u30c1\u30e3\u30e1\u30c1\u30e3\u9b54\u6cd5\u5b66\u5712\u751f\u6d3b","ncode":"N5131ES","userid":1191901,"writer":"Taiyou","story":"\u3053\u306e\u4e16\u754c\u306b\u306f4\u3064\u306e\u7a2e\u65cf\u304c\u5b58\u5728\u3057\u3066\u3044\u308b\u3002\u8056\u4eba\u3001\u9b54\u4eba\u3001\u4eba\u3001\u305d\u3057\u3066\u9b3c\u4eba\u2026\u2026\u305d\u3057\u3066\u9b3c\u4eba\u306e\u4e2d\u3067\u3082\u3063\u3068\u3082\u6050\u308c\u3089\u308c\u3066\u3044\u308b\u306e\u304c\u9b3c\u4eba\u306e\u5909\u7570\u7a2e\u300e\u5438\u8840\u9b3c\u300f\u3060\u3002\n\u5438\u8840\u9b3c\u3068\u306f\u9577\u304f\u3066500\u5e74\u306f\u751f\u304d\u3001\u305d\u306e\

明らかに先ほどとは違う結果になりました.
得られたデータの「\u9b3c\u4eba\u751f ...」などのuから始まる文字の羅列はUnicodeエスケープシーケンスというものだそうです.

実際に「"title"」の後の文字列を変換サイトで変換してみるとタイトルらしき文字列が得られました.

\u9b3c\u4eba\u751f\u5f92\u306e\u30cf\u30c1\u30e3\u30e1\u30c1\u30e3\u9b54\u6cd5\u5b66\u5712\u751f\u6d3b

↓変換

\鬼\人\生\徒\の\ハ\チ\ャ\メ\チ\ャ\魔\法\学\園\生\活

Unicode Escape Sequence | KWONLINE.ORG

JSON形式でタイトル情報だけ取得する

さらにオプションを追加して,タイトル情報だけ取得してみるように変更してみます.

r = http.request('GET','https://api.syosetu.com/novelapi/api',fields={'out':'json','of':'t'})

実行結果 (一部)

b'[{"allcount":563448},{"title":"\u5149\u3042\u308b\u6982\u5ff5\u306eLAST DAY"},{"title":"\u30a8\u30e1\u30e9\u30eb\u30c9\u30b0\u30ea\u30fc\u30f3\u306e\u6c34\u3067\u6cf3\u3050\u91d1\u9b5a"},{"title":"\u8056\u9280\u3068\u5de8\u5927\u90fd\u5e02\u300a\u30e1\u30ac\u30ed\u30dd\u30ea\u30b9\u300b"},{"title":"\u30b2\u30fc\u30e0\u30f2\u30bf\u30af\u306e\u30cb\u30fc\u30c8\u306e\u4ffa\u3060\u304c\u3001\u3053\u306e\u4e16\u754c\u3060\u3068\u82f1\u96c4\u3089\u3057\u3044"},{"title":"EMPEROR"},{"title":"\u5148\u751f\u306a\u3093\u304b\u3000\u5927\u3063\u5acc\u3044"},{"title":"\u65e5\u5e30\u308a\u3067\u7570\u4e16\u754c\u306b\u884c\u3063\u3066\u307f\u3088\u3046\uff01"},{"title":"\u79c1\u306e\u8a00\u8449\u306f\u3001\u307b\u308d\u307b\u308d\u3068\u3002"}

無事にJSON形式でタイトル情報のみを取得できたようです.
このように,URLのパラメータを変更することで様々な条件でデータを取得できるようです.

まとめ

今回は,とりあえずWebAPIを用いたデータの取得までは行うことができました.
なろう小説APIが特殊で,他のAPIの場合に応用できないという事態がないことを祈りたいです.
今後は得られたデータの扱い方(JSON形式)学んだり,実際に得られたデータを使って何かしらできないかを考えたいです.