17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
# File 'lib/ficrip/process.rb', line 17
def self.fetch(storyid)
base_url = "https://www.fanfiction.net/s/#{storyid}/"
primary_page = Retryable.retryable(tries: :infinite, on: OpenURI::HTTPError) do
Nokogiri::HTML open(base_url)
end
raise(ArgumentError.new("Invalid StoryID #{storyid}")) if primary_page.css('#profile_top').count == 0
title = primary_page.css('#profile_top > b').first.text
author = primary_page.css('#profile_top > a').first.text
Story.construct(title, author, base_url) do |s|
s.author_url = URI.join(base_url, primary_page.css('#profile_top > a').first['href'])
s.summary = primary_page.css('#profile_top > div').text
info = primary_page.css('#profile_top > span.xgray.xcontrast_txt').text.split(' - ')
s.rating = info.find_with 'Rated: Fiction'
s.language = info[1]
s.genres = info[2].split('/')
s.characters = info[3].strip
s.chapter_count = info.find_with('Chapters:').as { |c| c.parse_int unless c.nil? }
s.word_count = info.find_with('Words:').parse_int
s.review_count = info.find_with('Reviews:').parse_int
s.favs_count = info.find_with('Favs:').parse_int
s.follows_count = info.find_with('Follows:').parse_int
s.updated_date = info.find_with('Updated:').as do |d|
begin
Date.strptime(d, '%m/%d/%Y')
rescue
Date.strptime(d, '%m/%d') rescue (Time.now - ChronicDuration.parse(d)).to_date
end if d
end
s.published_date = info.find_with('Published:').as do |d|
begin
Date.strptime(d, '%m/%d/%Y')
rescue
Date.strptime(d, '%m/%d') rescue (Time.now - ChronicDuration.parse(d)).to_date
end
end
s.info_id = info.find_with('id:').to_i
raise(Exception.new("Error! StoryID and parsed ID don't match.")) if s.info_id != storyid
cover_elem = primary_page.css('img.lazy.cimage').first
s.cover_url = URI.join(base_url, cover_elem['data-original']) if cover_elem
chapter_select = primary_page.css('select#chap_select').first
if chapter_select
s.chapters = chapter_select.children.map(&:text)
else
s.chapters = ["1. #{title}"]
end
end
end
|