ちょっと最近Kindle PaperWhiteを書い直しまして,それと
小説家になろうをちらちらと読むようになった.
私はもともとしたらば掲示板にあるやる夫スレなどを読んでおり,それからすると小説家になろうの小説もまあまあ馴染みやすかったのでつい読んでしまう.
そこで,Kindleで素敵な組版で読めるといいなとおもったところ,
narou.rbの存在を知った.
しかしながら,(当然だが)既に商業化などに付き削除されてしまったものはnarou.rbじゃダウンロードも電子書籍化も不可能である.
だが,Web Archiveに生きている事は多々あり,これをEPUB3にして手元に保持しておきたいなあとか考え,次のスクリプトでnarou.rbで管理できる形に目次と小説本文をyaml形式で保存するスクレイピングスクリプトをつくった.
ぶっちゃけていうとこの素晴らしい世界に祝福を!
のWeb版のEPUBをコレクションしておきたかったというわけです.
以下,成果.
RubyもNokogiriもあまりよくわかってないのでイテレーションが非効率な気がするが,まあそんなに問題ないとおもう.
小説家になろうをちらちらと読むようになった.
私はもともとしたらば掲示板にあるやる夫スレなどを読んでおり,それからすると小説家になろうの小説もまあまあ馴染みやすかったのでつい読んでしまう.
そこで,Kindleで素敵な組版で読めるといいなとおもったところ,
narou.rbの存在を知った.
しかしながら,(当然だが)既に商業化などに付き削除されてしまったものはnarou.rbじゃダウンロードも電子書籍化も不可能である.
だが,Web Archiveに生きている事は多々あり,これをEPUB3にして手元に保持しておきたいなあとか考え,次のスクリプトでnarou.rbで管理できる形に目次と小説本文をyaml形式で保存するスクレイピングスクリプトをつくった.
ぶっちゃけていうとこの素晴らしい世界に祝福を!
以下,成果.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# encoding: utf-8 | |
# | |
# Web Archiveからスクレイピングして小説家になろうのテキストダウンロードと同じ形式でテキストパクってくるヤツ | |
# | |
require 'nokogiri' | |
require 'open-uri' | |
for i in 1..124 do | |
ans = [] | |
title = nil | |
begin | |
if 10 <= i and i <= 12 then | |
url = "http://web.archive.org/web/20130708184241/http://ncode.syosetu.com/n7145bl/#{i}" | |
else | |
url = "http://web.archive.org/web/20131127132412/http://ncode.syosetu.com/n7145bl/#{i}" | |
end | |
x = "" | |
open(url).each{ |d| | |
x += d.clone | |
} | |
doc = Nokogiri.HTML(x) | |
rescue | |
doc = Nokogiri.HTML("<html><body><p>abort</p></body></html>") | |
ans[ans.length] = "Nokogiri aborted" | |
end | |
begin | |
title_element = doc.xpath("//title").inner_text | |
title = title_element.sub(/^.* - /,"") | |
rescue | |
title = "Unknown" | |
end | |
begin | |
ans.push("#{title}\n\n") | |
doc.xpath("//div[@class='novel_view']").each do |node| | |
next if node.children.inner_text == nil | |
node.search('rb').each do |rb| rb.replace('|' + rb.inner_text) end | |
node.search('rt').each do |rt| rt.replace(rt.inner_text) end | |
node.search('rp').each do |rp| | |
rp.replace("《") if rp.inner_text == "(" | |
rp.replace("》") if rp.inner_text == ")" | |
end | |
node.search('ruby').each do |ruby| ruby.replace(ruby.inner_text) end | |
aa = node.inner_text.clone | |
ans.push(aa.clone) | |
end | |
File.open("#{i} #{title}.txt", 'w') { |file| | |
file.write ans.join("") | |
} | |
rescue | |
p "something wrong" | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# encoding: utf-8 | |
# | |
# Web Archiveからスクレイピングして小説家になろうの目次ページをnarou.rbのtoc.yamlと同じ形式で出力するやつ | |
# | |
require 'yaml' | |
require 'nokogiri' | |
require 'open-uri' | |
begin | |
url = "http://web.archive.org/web/20131127132412/http://ncode.syosetu.com/n7145bl/" | |
x = "" | |
open(url).each{ |d| | |
x += d.clone | |
} | |
doc = Nokogiri.HTML(x) | |
rescue | |
doc = Nokogiri.HTML("<html><body><p>abort</p></body></html>") | |
ans[ans.length] = "Nokogiri aborted" | |
end | |
begin | |
title = doc.xpath("//div[@class='novel_title']/div/a").inner_text | |
author = doc.xpath("//div[@class='novel_writername']/a[@href]").inner_text | |
toc_url = "http://ncode.syosetu.com/n7145bl/" | |
story = doc.xpath("//div[@class='novel_ex']").inner_text | |
ans = [] | |
idx = 1 | |
chapter = '' | |
subchapter = '' | |
change_chapter = false | |
# change_subchapter = false | |
doc.xpath("//div[@class='novel_sublist']/table/tr").each do |node| | |
if node.at(".//td[@class='chapter']") then | |
chapter = node.xpath(".//td[@class='chapter']").inner_text | |
change_chapter = true | |
else | |
nsa = node.xpath(".//td[@class='period_subtitle']/a[@href]")[0] | |
href = nsa.get_attribute("href").sub(/\/web\/20131127132412\/http:\/\/ncode.syosetu.com(.*$)/, '\1') | |
subtitle = nsa.inner_text | |
file_subtitle = subtitle | |
long_update = node.xpath(".//td[@class='long_update']")[0] | |
if long_update.at(".//span") then | |
span = long_update.xpath(".//span[@title]")[0] | |
subupdate = span.get_attribute("title").sub(/(.*) 改稿/, '\1') | |
subdate = long_update.inner_text.sub(/^\r\n(.*)\r\n\r\n(改)\r\n/, '\1') | |
else | |
subdate = long_update.inner_text.sub(/\r\n(.*)\r\n/, '\1') | |
subupdate = subdate | |
end | |
if change_chapter then | |
ans.push({"index"=>idx, "href"=>href, "chapter"=>chapter, "subchapter"=>"", "subtitle"=>subtitle, "file_subtitle"=>file_subtitle, "subdate"=>subdate, "subupdate"=>subupdate, "download_time"=>Time.now}) | |
change_chapter = false | |
else | |
ans.push({"index"=>idx, "href"=>href, "chapter"=>"", "subchapter"=>"", "subtitle"=>subtitle, "file_subtitle"=>file_subtitle, "subdate"=>subdate, "subupdate"=>subupdate, "download_time"=>Time.now}) | |
end | |
idx += 1 | |
end | |
File.open("toc.yaml", 'w') { |file| | |
YAML.dump({"title"=>title,"author"=>author,"toc_url"=>toc_url,"story"=>story,"subtitles"=>ans},file) | |
} | |
end | |
rescue | |
p "something wrong" | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# encoding: utf-8 | |
# | |
# Web Archiveからスクレイピングして小説家になろうのテキストダウンロードと同じ形式でテキストパクって, | |
# 更にそれをnarou.rbの本文のyaml形式で出力するやつ(実行場所の一階層上のディレクトリにtoc.yamlという目次があるものとする) | |
# | |
require 'yaml' | |
require 'nokogiri' | |
require 'open-uri' | |
toc = YAML.load_file('../toc.yaml')["subtitles"] | |
for i in 1..124 do | |
ans = [] | |
title = nil | |
begin | |
if 10 <= i and i <= 12 then | |
url = "http://web.archive.org/web/20130708184241/http://ncode.syosetu.com/n7145bl/#{i}" | |
else | |
url = "http://web.archive.org/web/20131127132412/http://ncode.syosetu.com/n7145bl/#{i}" | |
end | |
x = "" | |
open(url).each{ |d| | |
x += d.clone | |
} | |
doc = Nokogiri.HTML(x) | |
rescue | |
doc = Nokogiri.HTML("<html><body><p>abort</p></body></html>") | |
ans[ans.length] = "Nokogiri aborted" | |
end | |
begin | |
title_element = doc.xpath("//title").inner_text | |
title = title_element.sub(/^.* - /,"") | |
rescue | |
title = "Unknown" | |
end | |
begin | |
doc.xpath("//div[@class='novel_view']").each do |node| | |
next if node.children.inner_text == nil | |
node.search('rb').each do |rb| rb.replace('|' + rb.inner_text) end | |
node.search('rt').each do |rt| rt.replace(rt.inner_text) end | |
node.search('rp').each do |rp| | |
rp.replace("《") if rp.inner_text == "(" | |
rp.replace("》") if rp.inner_text == ")" | |
end | |
node.search('ruby').each do |ruby| ruby.replace(ruby.inner_text) end | |
aa = node.inner_text.clone | |
ans.push(aa.clone) | |
end | |
hash = toc[i-1] | |
File.open("#{i} #{title}.yaml", 'w') { |file| | |
hash.store("element", {"introduction"=>'',"body"=>ans.join(""),"postscript"=>'',"data_type"=>"text"}) | |
YAML.dump(hash,file) | |
} | |
rescue | |
p "something wrong" | |
end | |
end |