natalia 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/natalia/services/j_lyric.rb +125 -0
- data/lib/natalia/services/joysound.rb +2 -1
- data/lib/natalia/services/utamap.rb +2 -2
- data/lib/natalia/version.rb +1 -1
- data/lib/natalia.rb +5 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2656442ac7d8e82de97e949248c5bef87b51faef371254f8f9800d488f8c813
|
4
|
+
data.tar.gz: 2966d8b5a3fd4b2f8e623bfd37b562c8682831391ffa17cdfd68b756b2265e6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb91352464023b97cfb10c280b3687467241162e2a518b52b7f4b7dd67543bcf1ef8e439be091fb98dfad89bf28c9a16a79d9badf106e60e33125d853bb807b4
|
7
|
+
data.tar.gz: 6d404e9fac70e8b5d5e15d9db794091d73e4c0751356ebab7350077d1e5e2f5bfacd590c43fecbd7ab88a9506131fef647b0a4e5528eb7b22fd92d71c8050dc8
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'time'
|
5
|
+
require_relative '../utils'
|
6
|
+
|
7
|
+
module Natalia
|
8
|
+
module JLyric
|
9
|
+
# sort という概念はないっぽい
|
10
|
+
def self.search(keyword, type: :title, sort: :popularity_desc)
|
11
|
+
case type
|
12
|
+
when :title
|
13
|
+
search_by_title(keyword)
|
14
|
+
when :artist
|
15
|
+
search_by_artist(keyword, sort: sort)
|
16
|
+
else
|
17
|
+
raise ArgumentError, "unsupported search type `#{type}`"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.search_by_title(keyword)
|
22
|
+
entries = []
|
23
|
+
(1..).each do |page|
|
24
|
+
response =
|
25
|
+
Natalia::Utils.curl_get('https://search2.j-lyric.net/index.php', {
|
26
|
+
kt: keyword,
|
27
|
+
ct: '2', # kt 検索方法 (0: 前方, 1: 完全, 2: 中間, 3: 後方)
|
28
|
+
search: '検索', # 謎
|
29
|
+
ex: 'on', # 謎
|
30
|
+
ca: '2', # ka 検索方法
|
31
|
+
cl: '2', # kl 検索方法
|
32
|
+
p: page
|
33
|
+
})
|
34
|
+
response.value
|
35
|
+
|
36
|
+
doc = Nokogiri::HTML.parse(response.body)
|
37
|
+
table = doc.css('div#bas div#cnt div#mnb > div.bdy')
|
38
|
+
break if table.empty?
|
39
|
+
|
40
|
+
table.each do |body|
|
41
|
+
entries << {
|
42
|
+
source: self,
|
43
|
+
id: body.at_css('p.mid a')['href'].match(%r{/artist/(.+)\.html\z})[1],
|
44
|
+
title: body.at_css('p.mid a').content,
|
45
|
+
artist: body.css('p.sml')[0].at_css('a').content,
|
46
|
+
artist_id: body.css('p.sml')[0].at_css('a')['href'].match(%r{/artist/(.+)/\z})[1]
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
entries
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.search_by_artist(artist_id, sort: :popularity_desc)
|
55
|
+
response = Natalia::Utils.curl_get("https://j-lyric.net/artist/#{artist_id}/")
|
56
|
+
response.value
|
57
|
+
|
58
|
+
doc = Nokogiri::HTML.parse(response.body)
|
59
|
+
artist_name = doc.at_css('div#mnb div.cnt div.cap h2').content.match(/\A(.+)の歌詞リスト\z/)[1]
|
60
|
+
table = doc.css('div#bas div#cnt div#mnb div.bdy[id^=ly]')
|
61
|
+
|
62
|
+
entries = table.map do |row|
|
63
|
+
order, date, popularity = row.css('input[type=hidden]').map {|e| e['value']}
|
64
|
+
{
|
65
|
+
source: self,
|
66
|
+
id: row.at_css('p.ttl a')['href'].match(%r{/artist/(.+)\.html\z})[1],
|
67
|
+
title: row.at_css('p.ttl a').content,
|
68
|
+
artist: artist_name,
|
69
|
+
artist_id: artist_id,
|
70
|
+
order: order.to_i,
|
71
|
+
date: Time.parse("#{date} JST"),
|
72
|
+
popularity: -popularity.to_i
|
73
|
+
}
|
74
|
+
end.compact
|
75
|
+
|
76
|
+
case sort
|
77
|
+
when :title
|
78
|
+
entries.sort_by {|e| e[:order]}
|
79
|
+
when :title_desc
|
80
|
+
entries.sort_by {|e| -e[:order]}
|
81
|
+
when :popularity
|
82
|
+
entries.sort_by {|e| e[:popularity]}
|
83
|
+
when :popularity_desc
|
84
|
+
entries.sort_by {|e| -e[:popularity]}
|
85
|
+
when :date
|
86
|
+
entries.sort_by {|e| e[:date]}
|
87
|
+
when :date_desc
|
88
|
+
entries.sort_by {|e| -e[:date].to_i}
|
89
|
+
when :artist, :artist_desc
|
90
|
+
entries
|
91
|
+
else
|
92
|
+
raise ArgumentError, "unsupported sort type `#{sort}`"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.get(id)
|
97
|
+
response = Natalia::Utils.curl_get("https://j-lyric.net/artist/#{id}.html")
|
98
|
+
response.value
|
99
|
+
|
100
|
+
doc = Nokogiri::HTML.parse(response.body)
|
101
|
+
|
102
|
+
smls = doc.css('div#mnb div.lbdy p.sml')
|
103
|
+
|
104
|
+
ret = {
|
105
|
+
source: self,
|
106
|
+
id: id,
|
107
|
+
title: doc.at_css('div#mnb div.cap h2').content.match(/\A「(.+)」歌詞\z/)[1],
|
108
|
+
artist: smls[0].at_css('a').content,
|
109
|
+
artist_id: smls[0].at_css('a')['href'].match(%r{/artist/(.+)/\z})[1]
|
110
|
+
}
|
111
|
+
|
112
|
+
smls[1..].each do |e|
|
113
|
+
content = e.content
|
114
|
+
ret[:lyricist] = content.match(/作詞:(.+)/)[1] if content.start_with?('作詞:')
|
115
|
+
ret[:composer] = content.match(/作曲:(.+)/)[1] if content.start_with?('作曲:')
|
116
|
+
end
|
117
|
+
|
118
|
+
ret[:lyrics] = doc.at_css('p#Lyric').children.map do |e|
|
119
|
+
e.name == 'br' ? "\n" : e.content
|
120
|
+
end.join.strip
|
121
|
+
|
122
|
+
ret
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -24,7 +24,8 @@ module Natalia
|
|
24
24
|
|
25
25
|
def self.search(keyword, type: :title, sort: :popularity_desc)
|
26
26
|
sort = SORT_MAP[sort]
|
27
|
-
raise ArgumentError,
|
27
|
+
raise ArgumentError, "unsupported sort type `#{sort}`" unless sort
|
28
|
+
raise ArgumentError, "unsupported search type `#{type}`" unless KIND_MAP.key?(type)
|
28
29
|
|
29
30
|
response = Natalia::Utils.curl_post('https://mspxy.joysound.com/Common/ContentsList') do |request|
|
30
31
|
request.content_type = 'application/x-www-form-urlencoded; charset=UTF-8'
|
@@ -19,8 +19,8 @@ module Natalia
|
|
19
19
|
# @param [String] keyword キーワード(タイトル検索)、ID(それ以外)
|
20
20
|
def self.search(keyword, type: :title, sort: :popularity_desc)
|
21
21
|
sort = SORT_MAP[sort]
|
22
|
-
raise ArgumentError,
|
23
|
-
raise ArgumentError,
|
22
|
+
raise ArgumentError, "unsupported sort type `#{sort}`" unless sort
|
23
|
+
raise ArgumentError, "unsupported search type `#{type}`" unless %i[title artist lyricist composer arranger].include?(type)
|
24
24
|
|
25
25
|
entries = []
|
26
26
|
(type == :title ? 1.. : [1]).each do |page|
|
data/lib/natalia/version.rb
CHANGED
data/lib/natalia.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'natalia/services/j_lyric'
|
3
4
|
require_relative 'natalia/services/joysound'
|
4
5
|
require_relative 'natalia/services/utamap'
|
5
6
|
require_relative 'natalia/version'
|
@@ -44,6 +45,7 @@ module Natalia
|
|
44
45
|
# 信頼できるソース順に並べる
|
45
46
|
SERVICES = [
|
46
47
|
Natalia::Utamap,
|
48
|
+
Natalia::JLyric,
|
47
49
|
Natalia::Joysound
|
48
50
|
].freeze
|
49
51
|
|
@@ -51,6 +53,9 @@ module Natalia
|
|
51
53
|
entries = []
|
52
54
|
SERVICES.each do |service|
|
53
55
|
entries += service.search(keyword, type: :title, sort: sort)
|
56
|
+
rescue StandardError
|
57
|
+
warn "Failed to search by #{service}"
|
58
|
+
warn $!.full_message
|
54
59
|
end
|
55
60
|
entries.map {|entry| Song.new(entry)}
|
56
61
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: natalia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ishotihadus
|
@@ -37,6 +37,7 @@ files:
|
|
37
37
|
- README.md
|
38
38
|
- Rakefile
|
39
39
|
- lib/natalia.rb
|
40
|
+
- lib/natalia/services/j_lyric.rb
|
40
41
|
- lib/natalia/services/joysound.rb
|
41
42
|
- lib/natalia/services/utamap.rb
|
42
43
|
- lib/natalia/utils.rb
|