小説家になろうの本文をPHPで取得する方法(WordPressでの活用方法)

小説家になろう(以下「なろう」)に小説をのっけていて、例えば自分のサイトにも本文を載せたいと思っている方いますでしょうか?
一々コピペするのはクソ面倒くさいですよね。PHPを使えば楽になります。

手順を大きく分けると3つです。

1.PHPを使える環境を用意
2.なろうの本文をPHPで取得
3.WordPressで「2.」のPHPを使用

1は省略。レンタルサーバとか借りると大体PHPを実行する環境がついてきます。(最近は無料でPHPを使える環境を提供してくれるサービスもあるようですね)
2についてはphpQueryを使用。

phpQueryのダウンロードページから最新の「phpQuery-…-onefile.zip」をダウンロード。
https://code.google.com/archive/p/phpquery/downloads

サーバ内の好きなフォルダに格納してください。
phpQueryを呼び出す際、絶対パスで指定するため、格納したフォルダのパスを確認します。
PHPでパスを確認したい場合は、phpQueryを格納しているフォルダで下記のようなPHPを実行するとパスが分かります。

<?php
 echo dirname(__FILE__);
?>

さて、なろうでDOMを実施するためになろうのURL構造を把握しておく必要があります。
連載小説の場合、なろうのURL構造は下記のようになっています。
http://ncode.syosetu.com/Nコード/話数(例えば第一話だと「1」)

Nコードとは作品ごとに振られるユニークなコードです。
例えば拙作『機動生命体』のNコードは「n4254dm」です。

機動生命体、10話のURLは下記のようになります。

http://ncode.syosetu.com/n4254dm/10/

まずはなろうの本文を取得するPHPを作成します。
下記はNコードと話数を指定すると本文を取得してくるファンクションです。
なろうの本文はHTMLの

<div id="novel_honbun"~>

で記述されているので、その部分を抽出します。

<?php
// $ncode=Nコード $numが話数
function shownovel($ncode,$num){
	$path= "phpQueryを格納しているフォルダのパス";
	set_include_path($path);
	//phpQueryを呼び出し
	include($path .'/phpQuery-onefile.php');

	//なろうのページを取得
	$data = file_get_contents('http://ncode.syosetu.com/'.$ncode .'/' .$num);
	$html = phpQuery::newDocumentHTML($data);

	// 記事取得(HTML内のnovel_honbunの部分を抽出)
	$content = $html["#novel_honbun"];
	echo $content->html();
}
?>

このPHPをphpQueryを格納しているのと同じフォルダに格納します。
ファイル名は「shownovel.php」としておきましょう。

これでshownovel.phpを呼び出して、Nコードと話数を指定すると小説の本文を取得してきます。
shownovelを呼び出すPHPのサンプルプログラムは下記です。
『機動生命体』のNコード「n4254dm」と呼び出したい話数を指定します。
今回はためしに10話を呼び出します。

<?php
set_include_path("phpQueryとshownovel.phpを格納しているフォルダのパス");
$call_path = get_include_path();

//shownovel.phpを呼び出し。
include($call_path.'/shownovel.php');

//Nコードと話数を指定して本文を取得。
$value = shownovel("n4254dm","10");
?>

結果はこのようになります。

http://shigokiru.com/archives/1056/
HTMLをそのまま取り出しているので、ルビもそのまま出力されます。

ではこれをWordPressで使用してみましょう。
WordPressでPHPを使用するには主にショートコードを使用します。
ショートコードを使用する際はfunctions.phpに記載する方法もありますが、色々と大変なので、Post Snippetsプラグインを使います。

Post Snippets – HTMLやPHPコードを登録してショートコードで呼び出せるWordPressプラグイン

Post Snippets – HTMLやPHPコードを登録してショートコードで呼び出せるWordPressプラグイン

Post Snippetsで変数を使いたい場合は、『Variables』の欄に変数名を記入します。
複数の変数を使いたい場合は「,」で区切ります。

ncode,num

ショートコード内で上記の変数を使いたい場合は{}でくくります。
Post Snippetsで作ったショートコードのサンプルは下記です。

$ncode={ncode};
$num={num};

set_include_path("phpQueryとshownovel.phpを格納しているフォルダのパス");
$call_path = get_include_path();

include($call_path.'/shownovel.php');

$value = shownovel($ncode,$num);

WordPressの記事内でショートコードを呼び出したい時は、記事作成画面で、Post Snippetsのボタンが追加されていますので、
登録したショートコードを呼び出します。

ちなみに、shownovel.phpとショートコードを分けているのは、連載小説などで毎回Nコードを指定するのが面倒だからです。
連載小説を連続して貼り付けていく場合は一々Nコードを記述せず、ショートコードを書き直した方が効率的です。

$ncode="n4254dm";//ここでNコードを固定
$num={num};

set_include_path("phpQueryとshownovel.phpを格納しているフォルダのパス");
$call_path = get_include_path();

include($call_path.'/shownovel.php');

$value = shownovel($ncode,$num);

2016年10月12日時点のなろうの仕様に基づいて作成していますので、今後なろうの仕様改変により動作しない場合があります。

色々といじくりました

少し更新中で、色々見苦しい点ありましたが、現状これで一段落です。(気になるところは多少あるので少しずつ直していきます)
目立つ変更点は、まあ見た目ですが、以前からやりたかったコンテンツを追加しました。

小説家になろう との連携です。

前々から、思ってたのですが、「なろう」はブログをはじめ、SNS等との連携が悪すぎます。
例をあげると……って、あー、めんど。つまり言いたい事はなろうの更新情報をブログで通知するには一々手動で記事を書かなきゃいけないって事です。めんどくせぇ、めんどくせぇ……やってられないかったるい。
色々しらべると「なろう」はAtomフィードをサポートしてるのでRSSフィードで更新情報が通知できるようだったのでブログのウィジェットに表示してみました。当たり前ですが、これだと更新情報だけがずらずら出てくるので、連載小説とかやってると同じ小説のタイトルだけ延々と表示されるわけです。なんかやだよね。
っていうか、気づいたらこのブログに小説一覧が表示しているページが一切ない事に気づく。やべぇ。
でも、手動で一覧は作りたくない、作りたくない、めんどくさい、一回手動で作ったら、更新する度にリスト直さないといけないじゃん……
なんかお手軽プログラムとかないかなぁー、と思ったら、なかった。
でもなろうデベロッパー見てたらなんかPHPで作れそうな気がしてきた。

「なろうデベロッパー」

なろうデベロッパーでは、なろうから情報をとれる「なろう小説API(webapi)」を提供している。
つってもこのAPI、たいした機能はない。致命的なのが本文を取得する事ができない点だ。小説周辺のメタ情報しか拾ってこれない。
まあ、一覧作るくらいだったら別にいいかぁ、と思ってPHP組んだ。PHPはシンタックスが独特で構文チェック大変なんだけど、まあ、今は便利なツールが色々あるからね。

というわけで、なろうの小説一覧を表示するPHP作った。

一番最初のコメント行見ながらパラメータ変えれば誰の小説一覧でも作れます。

<?php
header('Content-Type: text/html; charset=UTF-8');

//------------------------ここに注目------------------------
//APIのURL
//lim=***の数値を変えると最大表示件数が変えられます。
//userid=***に作者のユーザID(半角数字6桁)を入力すると作者の作品一覧が表示されます。
$url='http://api.syosetu.com/novelapi/api/?out=json&lim=20&gzip=5&userid=521903';

//APIを取得
$file = file_get_contents($url);

//解凍する
$file=gzdecode($file);

//JSONデコード
$listarray=json_decode($file,true);

//展開する
foreach($listarray as $key=>$value){

    //要素0はcontinueで飛ばす
    if($key==0){continue;}

    //小説のURLを代入
    $novelurl='http://ncode.syosetu.com/'.strtolower($value['ncode']).'/';

    //タイトルの表示
    print '<big><b><a href="'.$novelurl.'">'.$value['title']."</a></big></b><br>";

    //URL表示リンク print '<a href="'.$novelurl.'">'.$novelurl.'</a>';

    //ジャンル表示Func_genre_strでジャンル(数値)を文字列に変換
    print "ジャンル:".Func_genre_str($value['genre'])."<br>";

    //最終更新日の表示
    print '<small>'."最終更新日:".$value['general_lastup']."<br>";

    //文字数の表示
    print "文字数:".$value['length']."字<br>";
    
    //読了時間(目安)の表示
    print "読了時間:".$value['time']."分(目安)</small><br><br>";

    //あらすじの表示
    print "あらすじ:<br>";
    print '<font size=1>'.nl2br($value['story'])."<br></font>";

    print '<hr>';

}

//ファンクション
//ジャンル(数値)を文字列に変換
function Func_genre_str($genre_str){
    $genre1=$genre_str;
    
    if($genre1==101){
        $genre_re = "異世界〔恋愛〕";
    } 
    if($genre1==102){
        $genre_re = "現実世界〔恋愛〕";
    }
    if($genre1==201){
        $genre_re = "ハイファンタジー〔ファンタジー〕";
    }
    if($genre1==202){
        $genre_re = "ローファンタジー〔ファンタジー〕";
    }
    if($genre1==301){
        $genre_re = "純文学〔文芸〕";
    }
    if($genre1==302){
        $genre_re = "ヒューマンドラマ〔文芸〕";
    }
    if($genre1==303){
        $genre_re = "歴史〔文芸〕";
    }
    if($genre1==304){
        $genre_re = "推理〔文芸〕";
    }
    if($genre1==305){
        $genre_re = "ホラー〔文芸〕";
    }
    if($genre1==306){
        $genre_re = "アクション〔文芸〕";
    }
    if($genre1==307){
        $genre_re = "コメディー〔文芸〕";
    }
    if($genre1==401){
        $genre_re = "VRゲーム〔SF〕";
    }
    if($genre1==402){
        $genre_re = "宇宙〔SF〕";
    }
    if($genre1==403){
        $genre_re = "空想科学〔SF〕";
    }
    if($genre1==404){
        $genre_re = "パニック〔SF〕";
    }
    if($genre1==9901){
        $genre_re = "童話〔その他〕";
    }
    if($genre1==9902){
        $genre_re = "詩〔その他〕";
    }
    if($genre1==9903){
        $genre_re = "エッセイ〔その他〕";
    }
    if($genre1==9904){
        $genre_re = "リプレイ〔その他〕";
    }
    if($genre1==9801){
        $genre_re = "ノンジャンル〔ノンジャンル〕";
    }
    if($genre1==9999){
        $genre_re = "その他〔その他〕";
    }
    return $genre_re;
}

?>

んで、上記のコードを実装して作ったページがこちら。
「作品一覧」

これで小説の一覧が自動更新されるようになったね、めでたしめでたし。