@@ -10,33 +10,87 @@ confirm_over18: no
10
10
append_title_to_folder_name : yes
11
11
title_strip_pattern : null
12
12
sitename : *name
13
- version : 1.0
13
+ version : 2.0
14
+
15
+ # ------------------------------------------------------------
16
+ # 前処理設定
17
+ # jsonを処理して正規表現で取得可能なデータへ変換し挿入する
18
+ code : &code
19
+ eval : |-
20
+ magicword = "KakuyomuPreprocessEvalMagicWord"
21
+ # magicwordがある場合、既にこの前処理が行われているので何もしない
22
+ unless source.include?(magicword)
23
+ require "json"
24
+ source.match(%r|<script id="__NEXT_DATA__" type="application/json">(.*)</script>|) do |m|
25
+ json = JSON.parse($1)
26
+ # data: 各データが収められたハッシュ
27
+ data = json["props"]["pageProps"]["__APOLLO_STATE__"]
28
+ # work: この作品のデータ
29
+ work = data["Work:#{json["query"]["workId"]}"]
30
+ # まずTOCを処理する
31
+ toc = work["tableOfContents"]
32
+ # workのTOCはTableOfContentsChapterの参照の配列となっているので、それを解決する
33
+ toc.map! {|v| data[v["__ref"]]}
34
+ # TableOfContentsChapterにはChapterと各話の配列があるのでそれを取り出し
35
+ toc.map! {|v| [v["chapter"], v["episodeUnions"]]}
36
+ # Chapterと各話を一つの配列にフラットにし
37
+ toc.flatten!
38
+ # Chapterが使われていない場合にあるnilを排除し
39
+ toc.compact!
40
+ # Chapterと各話は参照なので、それを解決し
41
+ toc.map! {|v| data[v["__ref"]]}
42
+ # 必要な属性値を取り出して「;」でつないでまとめる
43
+ # __typename: ChapterかEpisodeかの判別用
44
+ # level: Chapterにあり1か2かでchapterかsubchapterか判別する
45
+ # id: Episodeならindex値として必要。Chapterなら必要ないが処理の簡略化のため付加している
46
+ # publishedAt: Episodeにありsubupdateとして利用する
47
+ # title: Chapter、Episode共にタイトルとなる
48
+ # 最後のtitle以外で「;」を含む事は無いはず
49
+ toc_attr = %w(__typename level id publishedAt title)
50
+ toc.map! {|v| v.slice(*toc_attr).values.join(";")}
51
+ # 続いてworkの著者を処理する
52
+ # 著者の参照から表示用の名前 activityName を取得する
53
+ work["author"] = data[work["author"]["__ref"]]["activityName"]
54
+ # alternateAuthorName がある場合は、それも使う。
55
+ work["author"] = work["alternateAuthorName"] + "/" + work["author"] if work["alternateAuthorName"]
56
+ # あらすじの改行を<br>に変換し、正規表現を単純化する。<br>はnarourb側で再変換される
57
+ work["introduction"].gsub!("\n", "<br>")
58
+ # workからTOC以外に利用する属性を列挙している
59
+ work_attr = %w(author title serialStatus publicEpisodeCount publishedAt
60
+ editedAt lastEpisodePublishedAt totalCharacterCount introduction)
61
+ # HTMLコメントの開始、前処理済みか検知するためのmagicword、
62
+ # TOC以外のworkの利用する属性値、TOC、HTMLコメントの終了を生成し
63
+ str = ["<!---", magicword,
64
+ work.slice(*work_attr).map {|v| v.join("::")},
65
+ toc, "--->"].join("\n")
66
+ # 元のページデータに挿入する。デバッグ時用に元々のデータはすべて残す。
67
+ source.insert(m.begin(0), str)
68
+ # 元々のデータは基本必要ないのでreplaceを使えば元々のデータはすべて消える。
69
+ #source.replace(str)
70
+ end
71
+ end
72
+ nil
14
73
15
74
# ------------------------------------------------------------
16
75
# 書籍情報取得設定
17
- title : &title |-
18
- <h1 id="workTitle"><a href=".+?">(?<title>.+?)</a></h1>
19
- author : |-
20
- (?:<span class="activityName" itemprop="author">(?<author>.+?)</span>)|(?:<span class="screenName.*?">(?<author>.+?)</span>)
21
- story : &story |-
22
- <p id="introduction" class="ui-truncateTextButton js-work-introduction">(?<story>.+?)(?:[\n ]*?</span>|[\n ]*?</p>)
76
+ title : &title
77
+ - *code
78
+ - ^title::(?<title>.+?)$
79
+ author :
80
+ - ^author::(?<author>.+?)$
81
+ story : &story
82
+ - ^introduction::(?<story>.+?)$
23
83
24
84
# ------------------------------------------------------------
25
85
# 目次取得設定
26
86
toc_url : \\k<top_url>/works/\\k<ncode>
27
- subtitles : |-2
28
- (?:<li class="widget-toc-chapter widget-toc-level1.*?">
29
- <span>(?<chapter>.+?)</span>
30
- </li>
31
- )?(?:<li class="widget-toc-chapter widget-toc-level2.*?">
32
- <span>(?<subchapter>.+?)</span>
33
- </li>
34
- )?<li class="widget-toc-episode">
35
- <a href="(?<href>/works/\d+/episodes/(?<index>\d+))".*?>
36
- <span class="widget-toc-episode-titleLabel.*?">(?<subtitle>.+?)</span>
37
- <time class="widget-toc-episode-datePublished" datetime="(?<subupdate>.+?)">.+?</time>
38
- </a>
39
- </li>
87
+ subtitles :
88
+ - *code
89
+ - (?x)
90
+ ^(?:Chapter;1;\d+;(?<chapter>.+?)\n)?
91
+ (?:Chapter;2;\d+;(?<subchapter>.+?)\n)?
92
+ Episode;(?<index>\d+);(?<subupdate>.+?);(?<subtitle>.+?)$
93
+ href : /works/\\k<ncode>/episodes/\\k<index>
40
94
41
95
# ------------------------------------------------------------
42
96
# 本文取得設定
@@ -53,29 +107,28 @@ novel_info_url: \\k<toc_url>
53
107
t : *title
54
108
55
109
# novel_type 小説種別
56
- nt : ' <dt><span>執筆状況</span></dt>\n *?<dd> (?<novel_type>.+?)</dd> '
110
+ nt : ^serialStatus:: (?<novel_type>.+?)$
57
111
novel_type_string :
58
- 連載中 : 1
59
- 完結済 : 3
112
+ RUNNING : 1
113
+ COMPLETED : 3
60
114
61
115
# general_all_no 掲載話数
62
- ga : ' <dt><span>エピソード</span></dt>\n *?<dd> (?<general_all_no>\d+)話</dd> '
116
+ ga : ^publicEpisodeCount:: (?<general_all_no>.+?)$
63
117
64
118
# story あらすじ
65
119
s : *story
66
120
67
121
# general_firstup 初回掲載日
68
- gf : ' <dt><span>公開日</span></dt>\n *?<dd><time itemprop="datePublished" datetime=" (?<general_firstup>.+?)">.+?</time> '
122
+ gf : ^publishedAt:: (?<general_firstup>.+?)$
69
123
70
- # novelupdated_at 小説の更新時刻。最終掲載日で代用
71
- nu : ' <dt><span>最終更新日</span></dt>\n *?<dd><time itemprop="dateModified" datetime=" (?<novelupdated_at>.+?)">.+?</time> '
124
+ # novelupdated_at 小説の更新時刻
125
+ nu : ^editedAt:: (?<novelupdated_at>.+?)$
72
126
73
127
# general_lastup 最新話掲載日
74
- gl : null
128
+ gl : ^lastEpisodePublishedAt::(?<general_lastup>.+?)$
75
129
76
130
# writer 作者名
77
- w : |-
78
- (?:<span class="activityName" itemprop="author">(?<writer>.+?)</span>)|(?:<span class="screenName.*?">(?<writer>.+?)</span>)
131
+ w : ^author::(?<writer>.+?)$
79
132
80
133
# length 文字数
81
- l : ' <dt><span>総文字数</span></dt>\n *?<dd> (?<length>.+?)文字</dd> '
134
+ l : ^totalCharacterCount:: (?<length>.+?)$
0 commit comments