opendmm 0.0.2

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.
Files changed (179) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +3 -0
  5. data/README.md +9 -0
  6. data/Rakefile +77 -0
  7. data/bin/opendmm +24 -0
  8. data/lib/opendmm.rb +9 -0
  9. data/lib/opendmm/maker.rb +60 -0
  10. data/lib/opendmm/makers/aknr.rb +38 -0
  11. data/lib/opendmm/makers/ako3.rb +39 -0
  12. data/lib/opendmm/makers/anna_and_hanako.rb +40 -0
  13. data/lib/opendmm/makers/apa.rb +40 -0
  14. data/lib/opendmm/makers/aroma.rb +63 -0
  15. data/lib/opendmm/makers/attackers.rb +55 -0
  16. data/lib/opendmm/makers/aurora.rb +45 -0
  17. data/lib/opendmm/makers/baltan.rb +40 -0
  18. data/lib/opendmm/makers/befree.rb +42 -0
  19. data/lib/opendmm/makers/bi.rb +44 -0
  20. data/lib/opendmm/makers/bijin_majo.rb +39 -0
  21. data/lib/opendmm/makers/candy.rb +41 -0
  22. data/lib/opendmm/makers/caribbean.rb +40 -0
  23. data/lib/opendmm/makers/dip.rb +43 -0
  24. data/lib/opendmm/makers/dmm_collection.rb +39 -0
  25. data/lib/opendmm/makers/ebody.rb +42 -0
  26. data/lib/opendmm/makers/ideapocket.rb +68 -0
  27. data/lib/opendmm/makers/kawaii.rb +41 -0
  28. data/lib/opendmm/makers/kira_kira.rb +41 -0
  29. data/lib/opendmm/makers/madonna.rb +41 -0
  30. data/lib/opendmm/makers/moodyz.rb +48 -0
  31. data/lib/opendmm/makers/munekyunkissa.rb +42 -0
  32. data/lib/opendmm/makers/opera.rb +47 -0
  33. data/lib/opendmm/makers/oppai.rb +57 -0
  34. data/lib/opendmm/makers/premium.rb +43 -0
  35. data/lib/opendmm/makers/prestige.rb +66 -0
  36. data/lib/opendmm/makers/s1.rb +41 -0
  37. data/lib/opendmm/makers/sod.rb +44 -0
  38. data/lib/opendmm/makers/tameikegoro.rb +42 -0
  39. data/lib/opendmm/makers/to_satsu.rb +40 -0
  40. data/lib/opendmm/makers/waap.rb +46 -0
  41. data/lib/opendmm/search_engines/jav_library.rb +58 -0
  42. data/lib/opendmm/utils.rb +119 -0
  43. data/lib/opendmm/version.rb +3 -0
  44. data/opendmm.gemspec +25 -0
  45. data/test/fixtures/ABP-013.json +33 -0
  46. data/test/fixtures/ABS-014.json +31 -0
  47. data/test/fixtures/ABY-003.json +32 -0
  48. data/test/fixtures/ADN-019.json +37 -0
  49. data/test/fixtures/AIR-017.json +34 -0
  50. data/test/fixtures/AKO-011.json +20 -0
  51. data/test/fixtures/ALB-182.json +31 -0
  52. data/test/fixtures/ANND-066.json +29 -0
  53. data/test/fixtures/AP-001.json +24 -0
  54. data/test/fixtures/APAA-182.json +38 -0
  55. data/test/fixtures/APAK-051.json +42 -0
  56. data/test/fixtures/ARM-191.json +28 -0
  57. data/test/fixtures/ARMG-223.json +27 -0
  58. data/test/fixtures/ATID-183.json +41 -0
  59. data/test/fixtures/BBI-104.json +33 -0
  60. data/test/fixtures/BEB-001.json +35 -0
  61. data/test/fixtures/BF-175.json +31 -0
  62. data/test/fixtures/BID-017.json +40 -0
  63. data/test/fixtures/BIJN-006.json +25 -0
  64. data/test/fixtures/BLK-049.json +27 -0
  65. data/test/fixtures/BRA-002.json +34 -0
  66. data/test/fixtures/BWB-005.json +31 -0
  67. data/test/fixtures/CHN-008.json +31 -0
  68. data/test/fixtures/CHS-015.json +32 -0
  69. data/test/fixtures/CLUB-003.json +22 -0
  70. data/test/fixtures/CND-012.json +29 -0
  71. data/test/fixtures/CWM-156.json +34 -0
  72. data/test/fixtures/Carib 021511-620.json +27 -0
  73. data/test/fixtures/DCOL-017.json +25 -0
  74. data/test/fixtures/DGL-007.json +24 -0
  75. data/test/fixtures/DOM-045.json +36 -0
  76. data/test/fixtures/EBOD-109.json +30 -0
  77. data/test/fixtures/ECB-078.json +33 -0
  78. data/test/fixtures/EDD-189.json +33 -0
  79. data/test/fixtures/ESK-232.json +31 -0
  80. data/test/fixtures/EZD-369.json +32 -0
  81. data/test/fixtures/FSET-399.json +40 -0
  82. data/test/fixtures/HAZ-009.json +33 -0
  83. data/test/fixtures/HON-001.json +31 -0
  84. data/test/fixtures/IDBD-447.json +32 -0
  85. data/test/fixtures/INU-013.json +34 -0
  86. data/test/fixtures/IPSD-041.json +40 -0
  87. data/test/fixtures/IPTD-464.json +35 -0
  88. data/test/fixtures/IPTD-629.json +32 -0
  89. data/test/fixtures/IPZ-005.json +35 -0
  90. data/test/fixtures/JBD-153.json +42 -0
  91. data/test/fixtures/JBS-004.json +32 -0
  92. data/test/fixtures/JOB-010.json +33 -0
  93. data/test/fixtures/JUC-285.json +36 -0
  94. data/test/fixtures/JUFD-137.json +33 -0
  95. data/test/fixtures/JUX-007.json +35 -0
  96. data/test/fixtures/JUX-119.json +35 -0
  97. data/test/fixtures/KAWD-249.json +30 -0
  98. data/test/fixtures/KIRD-147.json +28 -0
  99. data/test/fixtures/KISD-042.json +32 -0
  100. data/test/fixtures/LLR-005.json +35 -0
  101. data/test/fixtures/MAS-042.json +36 -0
  102. data/test/fixtures/MBD-148.json +32 -0
  103. data/test/fixtures/MDC-002.json +33 -0
  104. data/test/fixtures/MDYD-544.json +34 -0
  105. data/test/fixtures/MEK-008.json +32 -0
  106. data/test/fixtures/MIAD-490.json +34 -0
  107. data/test/fixtures/MIDD-599.json +36 -0
  108. data/test/fixtures/MIDD-643.json +32 -0
  109. data/test/fixtures/MIDD-644.json +30 -0
  110. data/test/fixtures/MIDE-004.json +34 -0
  111. data/test/fixtures/MIGD-284.json +34 -0
  112. data/test/fixtures/MIGD-336.json +33 -0
  113. data/test/fixtures/MIGD-337.json +35 -0
  114. data/test/fixtures/MIMK-005.json +36 -0
  115. data/test/fixtures/MINT-004.json +35 -0
  116. data/test/fixtures/MIQD-010.json +27 -0
  117. data/test/fixtures/MIRD-071.json +41 -0
  118. data/test/fixtures/MIRD-072.json +47 -0
  119. data/test/fixtures/MIRD-073.json +38 -0
  120. data/test/fixtures/MIXS-005.json +34 -0
  121. data/test/fixtures/MMY-010.json +32 -0
  122. data/test/fixtures/NAGE-001.json +33 -0
  123. data/test/fixtures/NDR-001.json +32 -0
  124. data/test/fixtures/NOF-003.json +36 -0
  125. data/test/fixtures/NPS-130.json +18 -0
  126. data/test/fixtures/OBA-045.json +35 -0
  127. data/test/fixtures/ONSD-570.json +29 -0
  128. data/test/fixtures/OPUD-125.json +46 -0
  129. data/test/fixtures/OSR-003.json +32 -0
  130. data/test/fixtures/PARM-028.json +21 -0
  131. data/test/fixtures/PBD-134.json +29 -0
  132. data/test/fixtures/PGD-306.json +34 -0
  133. data/test/fixtures/PJD-085.json +31 -0
  134. data/test/fixtures/PPB-008.json +31 -0
  135. data/test/fixtures/PPP-001.json +45 -0
  136. data/test/fixtures/PPPD-102.json +33 -0
  137. data/test/fixtures/PPSD-028.json +40 -0
  138. data/test/fixtures/PPT-004.json +31 -0
  139. data/test/fixtures/PTS-230.json +17 -0
  140. data/test/fixtures/PTV-001.json +28 -0
  141. data/test/fixtures/PXD-027.json +37 -0
  142. data/test/fixtures/RAW-005.json +32 -0
  143. data/test/fixtures/RBD-183.json +40 -0
  144. data/test/fixtures/SAD-031.json +35 -0
  145. data/test/fixtures/SDDE-312.json +34 -0
  146. data/test/fixtures/SDMT-802.json +32 -0
  147. data/test/fixtures/SDMU-008.json +38 -0
  148. data/test/fixtures/SDNM-011.json +37 -0
  149. data/test/fixtures/SET-007.json +32 -0
  150. data/test/fixtures/SGA-001.json +31 -0
  151. data/test/fixtures/SHKD-415.json +38 -0
  152. data/test/fixtures/SNIS-041.json +34 -0
  153. data/test/fixtures/SOE-259.json +31 -0
  154. data/test/fixtures/SPC-001.json +31 -0
  155. data/test/fixtures/SPS-008.json +32 -0
  156. data/test/fixtures/SRS-015.json +32 -0
  157. data/test/fixtures/SSPD-077.json +44 -0
  158. data/test/fixtures/STAR-359.json +33 -0
  159. data/test/fixtures/SUPD-065.json +41 -0
  160. data/test/fixtures/TDT-018.json +31 -0
  161. data/test/fixtures/TMAM-034.json +14 -0
  162. data/test/fixtures/TMCY-039.json +14 -0
  163. data/test/fixtures/TMDI-040.json +14 -0
  164. data/test/fixtures/TMEM-044.json +14 -0
  165. data/test/fixtures/TMVI-042.json +14 -0
  166. data/test/fixtures/TRD-062.json +31 -0
  167. data/test/fixtures/URE-011.json +38 -0
  168. data/test/fixtures/WA-201.json +17 -0
  169. data/test/fixtures/WAT-003.json +33 -0
  170. data/test/fixtures/WPC-002.json +35 -0
  171. data/test/fixtures/WSS-231.json +33 -0
  172. data/test/fixtures/XND-023.json +32 -0
  173. data/test/fixtures/XV-100.json +18 -0
  174. data/test/fixtures/XV-1000.json +24 -0
  175. data/test/fixtures/YRH-008.json +35 -0
  176. data/test/fixtures/YRZ-009.json +32 -0
  177. data/test/fixtures/ZEX-068.json +18 -0
  178. data/test/fixtures_test.rb +76 -0
  179. metadata +454 -0
@@ -0,0 +1,41 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module Kawaii
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 'kawaiikawaii.jp'
9
+
10
+ def self.item(name)
11
+ case name
12
+ when /^(KAWD)-?(\d{3})$/i
13
+ get("/works/-/detail/=/cid=#{$1.downcase}#{$2}")
14
+ end
15
+ end
16
+ end
17
+
18
+ module Parser
19
+ def self.parse(content)
20
+ page_uri = content.request.last_uri
21
+ html = Nokogiri::HTML(content)
22
+ specs = Utils.hash_from_dl(html.css('#content > div.col540 > div > div.dvd_info > dl'))
23
+ return {
24
+ actresses: specs['出演者'].css('a').map(&:text),
25
+ code: (specs['DVD品番'] || spesc['Blu-ray品番']).text,
26
+ cover_image: html.at_css('#content > div.col300 > span.pake > p.textright > a > img')['src'].gsub(/pm.jpg$/, 'pl.jpg'),
27
+ description: html.css('#content > div.col540 > div > p.text').text,
28
+ genres: specs['ジャンル'].css('a').map(&:text),
29
+ movie_length: (specs['DVD収録時間'] || specs['Blu-ray収録時間']).text,
30
+ page: page_uri.to_s,
31
+ release_date: (specs['DVD発売日'] || specs['Blu-ray発売日']).text,
32
+ sample_images: html.css('#work_image_unit > a > img').map { |img| img['src'].gsub(/js(?=-\d+\.jpg$)/, 'jp') },
33
+ series: specs['シリーズ'].text,
34
+ title: html.css('#content > div.col540 > div > h3.worktitle').text,
35
+ thumbnail_image: html.at_css('#content > div.col300 > span.pake > p.textright > a > img')['src'],
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module KiraKira
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 'kirakira-av.com'
9
+
10
+ def self.item(name)
11
+ case name
12
+ when /^(BLK|KIRD|KISD|SET)-?(\d{3})$/i
13
+ get("/works/-/detail/=/cid=#{$1.downcase}#{$2}")
14
+ end
15
+ end
16
+ end
17
+
18
+ module Parser
19
+ def self.parse(content)
20
+ page_uri = content.request.last_uri
21
+ html = Nokogiri::HTML(content)
22
+ specs = Utils.hash_from_dl(html.xpath('//*[@id="wrap-works"]/section/section[2]/dl'))
23
+ return {
24
+ actresses: specs['出演女優'].css('ul > li').map(&:text),
25
+ code: specs['品番'].text,
26
+ cover_image: html.at_css('#slider > ul.slides > li:nth-child(1) > img')['src'],
27
+ description: html.xpath('//*[@id="wrap-works"]/section/section[1]/p').text,
28
+ genres: specs['ジャンル'].css('ul > li').map(&:text),
29
+ label: specs['レーベル'].text,
30
+ movie_length: specs['収録時間'].text,
31
+ page: page_uri.to_s,
32
+ release_date: specs['発売日'].text,
33
+ sample_images: html.css('#slider > ul.slides > li > img').map { |img| img['src'] }[1..-1],
34
+ thumbnail_image: html.at_css('#carousel > ul.slides > li:nth-child(1) > img')['src'],
35
+ title: html.css('#wrap-works > section > h1').text,
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module Madonna
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 'madonna-av.com'
9
+
10
+ def self.item(name)
11
+ case name
12
+ when /^(JUC|JUFD|JUX|OBA|URE)-?(\d{3})$/i
13
+ get("/works/-/detail/=/cid=#{$1.downcase}#{$2}")
14
+ end
15
+ end
16
+ end
17
+
18
+ module Parser
19
+ def self.parse(content)
20
+ page_uri = content.request.last_uri
21
+ html = Nokogiri::HTML(content)
22
+ specs = Utils.hash_from_dl(html.css('#column_contents > div > div.right_contents > dl'))
23
+ return {
24
+ actresses: specs['出演女優'].css('a').map(&:text),
25
+ code: specs['品番'].text.remove('DVD'),
26
+ cover_image: html.at_css('#column_contents > div > div.left_contents > div.pack > a')['href'],
27
+ description: html.css('#column_contents > div > div.left_contents > p').text,
28
+ directors: specs['監督'].text.split,
29
+ genres: specs['ジャンル'].text.split,
30
+ movie_length: specs['収録時間'].text.remove('DVD'),
31
+ page: page_uri.to_s,
32
+ release_date: specs['発売日'].text.remove('DVD'),
33
+ sample_images: html.css('#column_contents > div > div.left_contents > div.photo > ul > li > a').map { |a| a['href'] },
34
+ thumbnail_image: html.at_css('#column_contents > div > div.left_contents > div.pack > a > img')['src'],
35
+ title: html.css('#column_contents > h2').text,
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,48 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module Moodyz
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 'moodyz.com'
9
+
10
+ def self.item(name)
11
+ case name
12
+ when /^(MIAD|MIDD|MIDE|MIGD|MIMK|MINT|MIQD|MIRD|MIXS)-?(\d{3})$/i
13
+ $alpha = $1.downcase
14
+ $alpha.remove!(/d$/) if ( ($alpha == 'midd' && $2.to_i <= 643) ||
15
+ ($alpha == 'migd' && $2.to_i <= 336) ||
16
+ ($alpha == 'mird' && $2.to_i <= 72) )
17
+ get("/shop/-/detail/=/cid=#{$alpha}#{$2}")
18
+ end
19
+ end
20
+ end
21
+
22
+ module Parser
23
+ def self.parse(content)
24
+ page_uri = content.request.last_uri
25
+ html = Nokogiri::HTML(content)
26
+ specs = Utils.hash_by_split(html.xpath('//*[@id="nabi_information"]/ul/li[1]/dl/dd').map(&:text)).merge(
27
+ Utils.hash_by_split(html.xpath('//*[@id="nabi_information"]/ul/li').map(&:text)[1..-1]))
28
+ return {
29
+ actresses: html.xpath('//*[@id="works"]/dl/dt').map(&:text),
30
+ code: specs['品番'],
31
+ cover_image: html.at_xpath('//*[@id="works"]/span/a/p/img')['src'].gsub(/pm.jpg$/, 'pl.jpg'),
32
+ description: html.xpath('//*[@id="works"]/dl/dd').text,
33
+ directors: specs['▪監督'].split,
34
+ genres: specs['▪ジャンル'].split('/'),
35
+ label: specs['▪レーベル'],
36
+ movie_length: specs['収録時間'],
37
+ page: page_uri.to_s,
38
+ release_date: specs['発売日'],
39
+ sample_images: html.xpath('//*[@id="sample-pic"]/li/a/img').map { |img| img['src'].gsub(/js(?=-\d+\.jpg$)/, 'jp') },
40
+ series: specs['▪シリーズ'],
41
+ thumbnail_image: html.at_xpath('//*[@id="works"]/span/a/p/img')['src'],
42
+ title: html.xpath('//*[@id="main"]/ul[2]/h3/dl/dd/h2').text,
43
+ }
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,42 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module Munekyunkissa
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 'www.munekyunkissa.com'
9
+
10
+ def self.item(name)
11
+ case name
12
+ when /^(ALB)-?(\d{3})$/i
13
+ get("/works/#{$1.downcase}/#{$1.downcase}#{$2}.html")
14
+ end
15
+ end
16
+ end
17
+
18
+ module Parser
19
+ def self.parse(content)
20
+ page_uri = content.request.last_uri
21
+ html = Nokogiri::HTML(content)
22
+ specs = Utils.hash_from_dl(html.at_css('dl.data-left')).merge(
23
+ Utils.hash_from_dl(html.at_css('dl.data-right')))
24
+ return {
25
+ actresses: specs['出演者'].text.remove(':').split,
26
+ code: specs['品番'].text.remove(':'),
27
+ cover_image: html.at_css('div.ttl-pac a.ttl-package')['href'],
28
+ description: html.css('div.ttl-comment div.comment').text,
29
+ maker: '胸キュン喫茶',
30
+ movie_length: specs['収録時間'].text.remove(':'),
31
+ page: page_uri.to_s,
32
+ release_date: specs['発売日'].text.remove(':'),
33
+ sample_images: html.css('div.ttl-sample img').map { |img| img['src'] },
34
+ thumbnail_image: html.at_css('#main > div > div.main-detail > div.ttl-pac > a > img')['src'],
35
+ title: html.css('div.capt01').text,
36
+ # TODO: parse series, label, genres from pics
37
+ }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module Opera
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 'av-opera.jp'
9
+
10
+ def self.item(name)
11
+ case name
12
+ when /^(OPUD)-?(\d{3})$/i
13
+ get("/works/-/detail/=/cid=#{$1.downcase}#{$2}")
14
+ end
15
+ end
16
+ end
17
+
18
+ module Parser
19
+ def self.parse(content)
20
+ page_uri = content.request.last_uri
21
+ html = Nokogiri::HTML(Utils.force_utf8(content))
22
+ specs = Utils.hash_from_dl(html.css('#container-detail > div.pkg-data > div.data > dl.left-data')).merge(
23
+ Utils.hash_from_dl(html.css('#container-detail > div.pkg-data > div.data > dl.right-data')))
24
+ return {
25
+ actresses: specs['出演女優'].css('a').map(&:text),
26
+ code: specs['DVD品番'].text,
27
+ cover_image: html.at_css('div#container-detail > div.pkg-data > div.pkg > a > img')['src'].gsub(/pm.jpg$/, 'pl.jpg'),
28
+ description: html.css('#container-detail > div.pkg-data > div.comment-data').text,
29
+ directors: specs['監督'].css('a').map(&:text),
30
+ genres: specs['ジャンル'].css('a').map(&:text),
31
+ movie_length: specs['収録時間'].text,
32
+ page: page_uri.to_s,
33
+ release_date: specs['発売日'].text,
34
+ sample_images: html.css('#sample-pic > li > a > img').map { |img| img['src'].gsub(/js(?=-\d+\.jpg$)/, "jl") },
35
+ series: specs['シリーズ'].text.remove(':'),
36
+ thumbnail_image: html.at_css('div#container-detail > div.pkg-data > div.pkg > a > img')['src'],
37
+ title: html.xpath('//*[@id="container-detail"]/p[1]').text,
38
+ __extra: {
39
+ transsexual: specs['ニューハーフ'].css('a').map(&:text),
40
+ scatology: specs['スカトロ'].css('a').map(&:text),
41
+ },
42
+ }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,57 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module Oppai
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 'oppai-av.com'
9
+
10
+ def self.item(name)
11
+ case name
12
+ when /^(PPPD|PPSD)-?(\d{3})$/i
13
+ get("/works/-/detail/=/cid=#{$1.downcase}#{$2}")
14
+ end
15
+ end
16
+ end
17
+
18
+ module Parser
19
+ def self.parse(content)
20
+ page_uri = content.request.last_uri
21
+ html = Nokogiri::HTML(content)
22
+ specs = parse_specs(html)
23
+ return {
24
+ actresses: html.css('#content_main_detail > div > div.works_left > p.detail-actress > a').map(&:text),
25
+ boobs: specs['おっぱい'].text,
26
+ code: dvd(specs['品番'].text),
27
+ cover_image: html.at_css('#pake > dt > a')['href'],
28
+ description: html.css('#content_main_detail > div > div.works_left > p.detail_txt').text,
29
+ genres: specs['ジャンル'].css('a').map(&:text),
30
+ label: specs['レーベル'].text,
31
+ movie_length: dvd(specs['収録時間'].text),
32
+ page: page_uri.to_s,
33
+ release_date: dvd(specs['発売日'].text),
34
+ sample_images: html.css('#sample-pic > div > a').map { |a| a['href'] },
35
+ series: specs['シリーズ'].text,
36
+ thumbnail_image: html.at_css('#pake > dt > a > img')['src'],
37
+ title: html.css('#works-name').text,
38
+ }
39
+ end
40
+
41
+ private
42
+
43
+ def self.parse_specs(html)
44
+ html.css('#content_main_detail > div > div.works_right > ul > li').map do |li|
45
+ [ li.css('span.detail-capt').text,
46
+ li.css('span.detail-data')]
47
+ end.to_h
48
+ end
49
+
50
+ def self.dvd(text)
51
+ codes = Utils.hash_by_split(text.lines, '…')
52
+ codes['DVD']
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,43 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module Premium
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 'premium-beauty.com'
9
+
10
+ def self.item(name)
11
+ case name
12
+ when /^(PBD|PGD|PJD|PTV|PXD)-?(\d{3})$/i
13
+ get("/works/-/detail/=/cid=#{$1.downcase}#{$2}")
14
+ end
15
+ end
16
+ end
17
+
18
+ module Parser
19
+ def self.parse(content)
20
+ page_uri = content.request.last_uri
21
+ html = Nokogiri::HTML(content)
22
+ specs = Utils.hash_by_split(html.xpath('//*[@id="sub-navi"]/div[1]/div[1]/table/tr').map(&:text))
23
+ return {
24
+ actresses: html.css('#content > div > div > div.actress-list > dl > dd > a').map(&:text),
25
+ code: specs['DVD品番'] || specs['Blu-ray品番'],
26
+ cover_image: html.at_css('#pake')['href'],
27
+ description: html.css('#content > div > div > div.detail_text').text,
28
+ directors: specs['監督'].split,
29
+ genres: specs['ジャンル'].split('/'),
30
+ label: specs['レーベル'],
31
+ movie_length: specs['DVD収録時間'] || specs['Blu-ray収録時間'],
32
+ page: page_uri.to_s,
33
+ release_date: specs['発売日'],
34
+ sample_images: html.css('#sample_photo > li > a').map { |a| a['href'] },
35
+ series: specs['シリーズ'],
36
+ thumbnail_image: html.at_css('#pake > img')['src'],
37
+ title: html.css('#content > div > h2').text,
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,66 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module Prestige
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 'www.prestige-av.com'
9
+ cookies(adc: 1)
10
+
11
+ def self.item(name)
12
+ case name
13
+ when /^(ABP|ABS|ABY|BRA|CHN|CHS|DOM|EDD|ESK|EZD|HAZ|HON|INU|JBS|JOB|LLR|MAS|MBD|MDC|MEK|MMY|NDR|NOF|OSR|PPB|PPP|PPT|RAW|SAD|SGA|SPC|SRS|TAP|TDT|TRD|WAT|WPC|XND|YRH|YRZ)-?(\d{3})$/i
14
+ get("/item/prestige/#{$1.upcase}-#{$2}")
15
+ end
16
+ end
17
+ end
18
+
19
+ module Parser
20
+ def self.parse(content)
21
+ page_uri = content.request.last_uri
22
+ html = Nokogiri::HTML(content)
23
+ specs = Utils.hash_from_dl(html.css('div.product_detail_layout_01 dl.spec_layout'))
24
+ descriptions = parse_descriptions(html)
25
+ return {
26
+ actresses: parse_actresses(specs['出演:']),
27
+ code: specs['品番:'].text,
28
+ cover_image: html.at_css('div.product_detail_layout_01 p.package_layout a.sample_image')['href'],
29
+ description: [ descriptions['作品情報'].text, descriptions['レビュー'].text ].join,
30
+ genres: specs['ジャンル:'].css('a').map(&:text),
31
+ # TODO: Parse complete label, for example
32
+ # 'ABSOLUTELY P…' should be 'ABSOLUTELY PERFECT'
33
+ label: specs['レーベル:'].text,
34
+ maker: specs['メーカー名:'].text,
35
+ movie_length: specs['収録時間:'].text,
36
+ page: page_uri.to_s,
37
+ release_date: specs['発売日:'].text,
38
+ sample_images: descriptions['サンプル画像'].css('a.sample_image').map { |a| a['href'] },
39
+ series: specs['シリーズ:'].text,
40
+ thumbnail_image: html.at_css('#Wrapper > div.main_layout_01 > div.box_705 > div.section.product_layout_01 > div.product_detail_layout_01 > p > a > img')['src'],
41
+ title: html.css('div.product_title_layout_01').text,
42
+ }
43
+ end
44
+
45
+ private
46
+
47
+ def self.parse_descriptions(html)
48
+ layouts = html.css('div.product_layout_01 div.product_description_layout_01')
49
+ titles = layouts.css('h2.title').map(&:text)
50
+ contents = layouts.css('.contents')
51
+ Hash[titles.zip(contents)]
52
+ end
53
+
54
+ def self.parse_actresses(node)
55
+ if node.nil?
56
+ nil
57
+ elsif !node.css('a').empty?
58
+ node.css('a').map(&:text)
59
+ else
60
+ [ node.text ]
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,41 @@
1
+ module OpenDMM
2
+ module Maker
3
+ module S1
4
+ include Maker
5
+
6
+ module Site
7
+ include HTTParty
8
+ base_uri 's1s1s1.com'
9
+
10
+ def self.item(name)
11
+ case name
12
+ when /^(ONSD|SNIS|SOE|SPS)-?(\d{3})$/i
13
+ get("/works/-/detail/=/cid=#{$1.downcase}#{$2}")
14
+ end
15
+ end
16
+ end
17
+
18
+ module Parser
19
+ def self.parse(content)
20
+ page_uri = content.request.last_uri
21
+ html = Nokogiri::HTML(content)
22
+ specs = Utils.hash_from_dl(html.xpath('//*[@id="contents"]/dl'))
23
+ return {
24
+ actresses: specs['女優'].text.split,
25
+ code: html.xpath('//*[@id="order"]/tr[1]/td[1]').text,
26
+ cover_image: html.at_xpath('//*[@id="slide-photo"]/div[@class="slide pake"]/img')['src'],
27
+ description: html.css('#contents > p.tx-comment').text,
28
+ directors: specs['監督'].text.split,
29
+ genres: specs['ジャンル'].css('a').map(&:text),
30
+ page: page_uri.to_s,
31
+ release_date: specs['発売日'].text,
32
+ sample_images: html.xpath('//*[@id="slide-photo"]/div[contains(@class, "slide") and not(contains(@class, "pake"))]/img').map { |img| img['src'] },
33
+ series: specs['シリーズ'].text,
34
+ thumbnail_image: html.at_css('#slide-thumbnail > ul.ts_container > li.ts_thumbnails > div.ts_preview_wrapper > ul.ts_preview > li > img')['src'],
35
+ title: html.css('#contents > h1').text,
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end