opendmm 0.4.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +3 -133
- data/bin/opendmm +21 -18
- data/dev.thor +17 -0
- data/lib/opendmm.rb +19 -49
- data/lib/opendmm/engines/av_entertainments.rb +81 -0
- data/lib/opendmm/engines/caribbean.rb +106 -0
- data/lib/opendmm/engines/caribbean_pr.rb +65 -0
- data/lib/opendmm/engines/heyzo.rb +49 -0
- data/lib/opendmm/engines/jav_library.rb +81 -0
- data/lib/opendmm/engines/one_pondo.rb +53 -0
- data/lib/opendmm/engines/tokyo_hot.rb +78 -0
- data/lib/opendmm/movie.rb +106 -0
- data/lib/opendmm/utils/chronic_duration.rb +17 -0
- data/lib/opendmm/utils/date.rb +19 -0
- data/lib/opendmm/utils/httparty.rb +30 -0
- data/lib/opendmm/utils/logger.rb +6 -0
- data/lib/opendmm/utils/nokogiri.rb +14 -0
- data/lib/opendmm/version.rb +1 -1
- data/opendmm.gemspec +2 -0
- data/templates/engine.tt +33 -0
- data/test/flow_test.rb +33 -0
- metadata +47 -457
- data/.travis.yml +0 -6
- data/lib/opendmm/maker.rb +0 -33
- data/lib/opendmm/makers/aknr.rb +0 -22
- data/lib/opendmm/makers/ako3.rb +0 -22
- data/lib/opendmm/makers/apa.rb +0 -23
- data/lib/opendmm/makers/aroma.rb +0 -48
- data/lib/opendmm/makers/attackers.rb +0 -36
- data/lib/opendmm/makers/aurora.rb +0 -29
- data/lib/opendmm/makers/baltan.rb +0 -24
- data/lib/opendmm/makers/befree.rb +0 -26
- data/lib/opendmm/makers/bi.rb +0 -28
- data/lib/opendmm/makers/candy.rb +0 -32
- data/lib/opendmm/makers/caribbean.rb +0 -25
- data/lib/opendmm/makers/caribbeanpr.rb +0 -33
- data/lib/opendmm/makers/cross.rb +0 -26
- data/lib/opendmm/makers/das.rb +0 -36
- data/lib/opendmm/makers/dip.rb +0 -26
- data/lib/opendmm/makers/dmm_collection.rb +0 -23
- data/lib/opendmm/makers/doc.rb +0 -56
- data/lib/opendmm/makers/ebody.rb +0 -26
- data/lib/opendmm/makers/g_area.rb +0 -59
- data/lib/opendmm/makers/ideapocket.rb +0 -28
- data/lib/opendmm/makers/kawaii.rb +0 -25
- data/lib/opendmm/makers/kira_kira.rb +0 -25
- data/lib/opendmm/makers/madonna.rb +0 -25
- data/lib/opendmm/makers/moodyz.rb +0 -45
- data/lib/opendmm/makers/munekyunkissa.rb +0 -25
- data/lib/opendmm/makers/one_pondo.rb +0 -44
- data/lib/opendmm/makers/opera.rb +0 -29
- data/lib/opendmm/makers/oppai.rb +0 -39
- data/lib/opendmm/makers/premium.rb +0 -26
- data/lib/opendmm/makers/prestige.rb +0 -47
- data/lib/opendmm/makers/ran_maru.rb +0 -35
- data/lib/opendmm/makers/s1.rb +0 -25
- data/lib/opendmm/makers/s_cute.rb +0 -47
- data/lib/opendmm/makers/sod.rb +0 -27
- data/lib/opendmm/makers/tameikegoro.rb +0 -24
- data/lib/opendmm/makers/ten_musume.rb +0 -33
- data/lib/opendmm/makers/tokyo_247.rb +0 -41
- data/lib/opendmm/makers/waap.rb +0 -28
- data/lib/opendmm/makers/xxx.rb +0 -43
- data/lib/opendmm/makers_broken/anna_and_hanako.rb +0 -24
- data/lib/opendmm/makers_broken/high_scene.rb +0 -32
- data/lib/opendmm/makers_broken/to_satsu.rb +0 -24
- data/lib/opendmm/search_engine.rb +0 -20
- data/lib/opendmm/search_engines/av_entertainments.rb +0 -46
- data/lib/opendmm/search_engines/dmm.rb +0 -50
- data/lib/opendmm/search_engines/jav_library.rb +0 -39
- data/lib/opendmm/search_engines/mgstage.rb +0 -41
- data/lib/opendmm/site.rb +0 -80
- data/lib/opendmm/utils.rb +0 -126
- data/test/av_entertainments_fixtures/MKBD-S40.json +0 -36
- data/test/av_entertainments_fixtures/SKYHD-108.json +0 -53
- data/test/av_entertainments_fixtures/sky107.json +0 -33
- data/test/broken/ANND-066.json +0 -30
- data/test/broken/BIJN-006.json +0 -26
- data/test/broken/CLUB-003.json +0 -23
- data/test/broken/HIGH-107.json +0 -29
- data/test/broken/SIRO-1088.json +0 -29
- data/test/dmm_fixtures/DMYJ-001.json +0 -20
- data/test/dmm_fixtures/KHY-009.json +0 -21
- data/test/dmm_fixtures/RKI-294.json +0 -31
- data/test/dmm_fixtures/dmyj00001.json +0 -20
- data/test/dmm_fixtures/dmyj001.json +0 -20
- data/test/fixture_test.rb +0 -83
- data/test/jav_library_fixtures/DLY-0001.json +0 -21
- data/test/jav_library_fixtures/DLY-001.json +0 -18
- data/test/jav_library_fixtures/JUFD-379.json +0 -25
- data/test/jav_library_fixtures/XV-100.json +0 -18
- data/test/jav_library_fixtures/XV-1000.json +0 -24
- data/test/jav_library_fixtures/xv100.json +0 -18
- data/test/maker_fixtures/10musume 082914_01.json +0 -31
- data/test/maker_fixtures/1pondo 011111_006.json +0 -35
- data/test/maker_fixtures/1pondo 022506_835.json +0 -8
- data/test/maker_fixtures/352_kokona_02.json +0 -26
- data/test/maker_fixtures/ABP-013.json +0 -33
- data/test/maker_fixtures/ABS-014.json +0 -31
- data/test/maker_fixtures/ABY-003.json +0 -32
- data/test/maker_fixtures/ADN-019.json +0 -38
- data/test/maker_fixtures/ADN-025.json +0 -37
- data/test/maker_fixtures/AIR-017.json +0 -34
- data/test/maker_fixtures/AKO-011.json +0 -20
- data/test/maker_fixtures/ALB-038.json +0 -30
- data/test/maker_fixtures/ALB-182.json +0 -31
- data/test/maker_fixtures/AP-001.json +0 -24
- data/test/maker_fixtures/APAA-182.json +0 -38
- data/test/maker_fixtures/APAK-051.json +0 -42
- data/test/maker_fixtures/ARM-191.json +0 -28
- data/test/maker_fixtures/ARMG-223.json +0 -27
- data/test/maker_fixtures/ATID-183.json +0 -41
- data/test/maker_fixtures/AVOP-061.json +0 -29
- data/test/maker_fixtures/BBI-104.json +0 -34
- data/test/maker_fixtures/BEB-001.json +0 -36
- data/test/maker_fixtures/BF-175.json +0 -32
- data/test/maker_fixtures/BF-254.json +0 -22
- data/test/maker_fixtures/BF-263.json +0 -32
- data/test/maker_fixtures/BID-017.json +0 -41
- data/test/maker_fixtures/BLK-049.json +0 -28
- data/test/maker_fixtures/BRA-002.json +0 -34
- data/test/maker_fixtures/BWB-005.json +0 -32
- data/test/maker_fixtures/CEN-033.json +0 -35
- data/test/maker_fixtures/CHN-008.json +0 -31
- data/test/maker_fixtures/CHS-015.json +0 -32
- data/test/maker_fixtures/CND-012.json +0 -30
- data/test/maker_fixtures/CND-062.json +0 -30
- data/test/maker_fixtures/CRAD-099.json +0 -38
- data/test/maker_fixtures/CRPD-451.json +0 -30
- data/test/maker_fixtures/CRS-056.json +0 -18
- data/test/maker_fixtures/CRSS-013.json +0 -39
- data/test/maker_fixtures/CWM-156.json +0 -34
- data/test/maker_fixtures/Carib 021511-620.json +0 -28
- data/test/maker_fixtures/Caribpr 082914_940.json +0 -31
- data/test/maker_fixtures/DASD-001.json +0 -30
- data/test/maker_fixtures/DAZD-001.json +0 -27
- data/test/maker_fixtures/DCOL-017.json +0 -26
- data/test/maker_fixtures/DGL-007.json +0 -25
- data/test/maker_fixtures/DGL-066.json +0 -26
- data/test/maker_fixtures/DOM-045.json +0 -36
- data/test/maker_fixtures/EBOD-109.json +0 -31
- data/test/maker_fixtures/ECB-078.json +0 -33
- data/test/maker_fixtures/EDD-189.json +0 -33
- data/test/maker_fixtures/ESK-232.json +0 -31
- data/test/maker_fixtures/EZD-369.json +0 -32
- data/test/maker_fixtures/FSET-399.json +0 -41
- data/test/maker_fixtures/FTN-002.json +0 -15
- data/test/maker_fixtures/GDW-006.json +0 -18
- data/test/maker_fixtures/HAZ-009.json +0 -33
- data/test/maker_fixtures/HON-001.json +0 -31
- data/test/maker_fixtures/IDBD-447.json +0 -31
- data/test/maker_fixtures/INF-003.json +0 -19
- data/test/maker_fixtures/INU-013.json +0 -34
- data/test/maker_fixtures/IPSD-041.json +0 -38
- data/test/maker_fixtures/IPTD-464.json +0 -34
- data/test/maker_fixtures/IPTD-629.json +0 -31
- data/test/maker_fixtures/IPZ-005.json +0 -33
- data/test/maker_fixtures/JBD-153.json +0 -42
- data/test/maker_fixtures/JBS-004.json +0 -32
- data/test/maker_fixtures/JOB-010.json +0 -33
- data/test/maker_fixtures/JUC-285.json +0 -37
- data/test/maker_fixtures/JUFD-137.json +0 -34
- data/test/maker_fixtures/JUX-007.json +0 -36
- data/test/maker_fixtures/JUX-119.json +0 -36
- data/test/maker_fixtures/KAWD-249.json +0 -31
- data/test/maker_fixtures/KAWD-315.json +0 -32
- data/test/maker_fixtures/KIRD-147.json +0 -29
- data/test/maker_fixtures/KISD-042.json +0 -33
- data/test/maker_fixtures/LLR-005.json +0 -35
- data/test/maker_fixtures/LNS-003.json +0 -15
- data/test/maker_fixtures/MAS-042.json +0 -36
- data/test/maker_fixtures/MBD-148.json +0 -32
- data/test/maker_fixtures/MDC-002.json +0 -33
- data/test/maker_fixtures/MDYD-544.json +0 -31
- data/test/maker_fixtures/MDYD-863.json +0 -29
- data/test/maker_fixtures/MEK-008.json +0 -32
- data/test/maker_fixtures/MIAD-490.json +0 -35
- data/test/maker_fixtures/MIDD-599.json +0 -37
- data/test/maker_fixtures/MIDD-643.json +0 -33
- data/test/maker_fixtures/MIDD-644.json +0 -31
- data/test/maker_fixtures/MIDE-004.json +0 -35
- data/test/maker_fixtures/MIGD-284.json +0 -35
- data/test/maker_fixtures/MIGD-336.json +0 -34
- data/test/maker_fixtures/MIGD-337.json +0 -36
- data/test/maker_fixtures/MIMK-005.json +0 -37
- data/test/maker_fixtures/MINT-004.json +0 -36
- data/test/maker_fixtures/MIQD-010.json +0 -28
- data/test/maker_fixtures/MIRD-071.json +0 -42
- data/test/maker_fixtures/MIRD-072.json +0 -48
- data/test/maker_fixtures/MIRD-073.json +0 -39
- data/test/maker_fixtures/MIXS-005.json +0 -35
- data/test/maker_fixtures/MMY-010.json +0 -32
- data/test/maker_fixtures/NAGE-001.json +0 -33
- data/test/maker_fixtures/NDR-001.json +0 -32
- data/test/maker_fixtures/NLF-001.json +0 -15
- data/test/maker_fixtures/NOF-003.json +0 -36
- data/test/maker_fixtures/NPS-130.json +0 -18
- data/test/maker_fixtures/NRS-012.json +0 -17
- data/test/maker_fixtures/OBA-045.json +0 -36
- data/test/maker_fixtures/ONSD-570.json +0 -29
- data/test/maker_fixtures/OPUD-001.json +0 -41
- data/test/maker_fixtures/OPUD-125.json +0 -45
- data/test/maker_fixtures/OSR-003.json +0 -32
- data/test/maker_fixtures/PARM-028.json +0 -21
- data/test/maker_fixtures/PBD-134.json +0 -33
- data/test/maker_fixtures/PGD-306.json +0 -33
- data/test/maker_fixtures/PJD-085.json +0 -30
- data/test/maker_fixtures/PLA-001.json +0 -29
- data/test/maker_fixtures/PPB-008.json +0 -31
- data/test/maker_fixtures/PPP-001.json +0 -45
- data/test/maker_fixtures/PPPD-102.json +0 -34
- data/test/maker_fixtures/PPSD-028.json +0 -41
- data/test/maker_fixtures/PPT-004.json +0 -31
- data/test/maker_fixtures/PTS-230.json +0 -17
- data/test/maker_fixtures/PTV-001.json +0 -29
- data/test/maker_fixtures/PXD-024.json +0 -31
- data/test/maker_fixtures/PXD-027.json +0 -37
- data/test/maker_fixtures/Perfect-G 430mei.json +0 -18
- data/test/maker_fixtures/Perfect-G 481yuuka.json +0 -18
- data/test/maker_fixtures/Perfect-G Docle yoriko2.json +0 -19
- data/test/maker_fixtures/Perfect-G kumie.json +0 -18
- data/test/maker_fixtures/Perfect-G le_yoriko2.json +0 -19
- data/test/maker_fixtures/Perfect-G yoriko2 Docle.json +0 -19
- data/test/maker_fixtures/RAW-005.json +0 -32
- data/test/maker_fixtures/RBD-183.json +0 -40
- data/test/maker_fixtures/RDT-190.json +0 -20
- data/test/maker_fixtures/RTP-005.json +0 -21
- data/test/maker_fixtures/RTP-025.json +0 -12
- data/test/maker_fixtures/S-Cute 248_hibiki_07.json +0 -26
- data/test/maker_fixtures/S-Cute 352_kokona_02.json +0 -26
- data/test/maker_fixtures/S-Cute 353_rena_01.json +0 -26
- data/test/maker_fixtures/S-Cute ps5_07_rimu.json +0 -26
- data/test/maker_fixtures/S-Cute ps6_99_reona.json +0 -26
- data/test/maker_fixtures/S-Cute ps7_83_akari2.json +0 -26
- data/test/maker_fixtures/S-Cute swm_05_risa2.json +0 -26
- data/test/maker_fixtures/SAD-031.json +0 -35
- data/test/maker_fixtures/SDDE-312.json +0 -34
- data/test/maker_fixtures/SDMT-802.json +0 -32
- data/test/maker_fixtures/SDMU-008.json +0 -38
- data/test/maker_fixtures/SDNM-011.json +0 -37
- data/test/maker_fixtures/SET-007.json +0 -33
- data/test/maker_fixtures/SGA-001.json +0 -32
- data/test/maker_fixtures/SHKD-415.json +0 -38
- data/test/maker_fixtures/SNIS-041.json +0 -35
- data/test/maker_fixtures/SOE-259.json +0 -32
- data/test/maker_fixtures/SOE-379.json +0 -28
- data/test/maker_fixtures/SPC-001.json +0 -31
- data/test/maker_fixtures/SPS-008.json +0 -33
- data/test/maker_fixtures/SRS-015.json +0 -32
- data/test/maker_fixtures/SSPD-077.json +0 -44
- data/test/maker_fixtures/STAR-359.json +0 -33
- data/test/maker_fixtures/SUPD-065.json +0 -40
- data/test/maker_fixtures/TDT-018.json +0 -31
- data/test/maker_fixtures/TMAM-034.json +0 -15
- data/test/maker_fixtures/TMCY-039.json +0 -15
- data/test/maker_fixtures/TMDI-040.json +0 -15
- data/test/maker_fixtures/TMEM-044.json +0 -15
- data/test/maker_fixtures/TMVI-042.json +0 -15
- data/test/maker_fixtures/TRD-062.json +0 -31
- data/test/maker_fixtures/TYOD-232.json +0 -21
- data/test/maker_fixtures/Tokyo 247 371yui.json +0 -35
- data/test/maker_fixtures/ULT-013.json +0 -15
- data/test/maker_fixtures/URE-011.json +0 -39
- data/test/maker_fixtures/VVP-001.json +0 -17
- data/test/maker_fixtures/WA-201.json +0 -17
- data/test/maker_fixtures/WAT-003.json +0 -33
- data/test/maker_fixtures/WDI-037.json +0 -38
- data/test/maker_fixtures/WPC-002.json +0 -35
- data/test/maker_fixtures/WSS-231.json +0 -33
- data/test/maker_fixtures/XND-023.json +0 -32
- data/test/maker_fixtures/XXX 21685.json +0 -17
- data/test/maker_fixtures/YRH-008.json +0 -35
- data/test/maker_fixtures/YRZ-009.json +0 -32
- data/test/maker_fixtures/YUM-001.json +0 -12
- data/test/maker_fixtures/ZEX-068.json +0 -18
@@ -1,32 +0,0 @@
|
|
1
|
-
base_uri 'highscene.jp'
|
2
|
-
|
3
|
-
register_product(
|
4
|
-
/^(HIGH)-?(\d{3})$/i,
|
5
|
-
'/works/-/detail/=/cid=#{$1.downcase}#{$2}/',
|
6
|
-
)
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
def self.parse_product_html(html)
|
11
|
-
specs = Utils.hash_by_split html.css('#works-details > dl > dd > p').map(&:text)
|
12
|
-
{
|
13
|
-
actresses: [ html.css('#content > h2').text[/(?<=>>).*/] ],
|
14
|
-
# brand: String
|
15
|
-
# categories: Array
|
16
|
-
cover_image: html.at_css('#actimg > li > a')['href'],
|
17
|
-
description: html.css('#works-details > p.works-txt').text,
|
18
|
-
# directors: Array
|
19
|
-
genres: specs['ジャンル'].split('/'),
|
20
|
-
label: specs['レーベル'],
|
21
|
-
maker: 'High Scene',
|
22
|
-
movie_length: specs['収録時間'],
|
23
|
-
release_date: specs['配信日'],
|
24
|
-
sample_images: html.css('#actimg > li > a')[1..-1].map { |a| a['href'] },
|
25
|
-
# scenes: Array
|
26
|
-
# series: String
|
27
|
-
subtitle: html.css('#works-details > dl > dt > span').text,
|
28
|
-
# theme: String
|
29
|
-
thumbnail_image: html.at_css('#actimg > li > a > img')['src'],
|
30
|
-
title: html.css('#content > h2').text[/(?<=>>).*/],
|
31
|
-
}
|
32
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
base_uri 'to-satsu.com'
|
2
|
-
|
3
|
-
register_product(
|
4
|
-
/^(CLUB)-?(\d{3})$/i,
|
5
|
-
'/works/#{$1.downcase}/#{$1.downcase}#{$2}/#{$1.downcase}#{$2}.html',
|
6
|
-
)
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
def self.parse_product_html(html)
|
11
|
-
specs = Utils.hash_from_dl(html.css('#main > div > div.main-detail > div.ttl-data > dl'))
|
12
|
-
{
|
13
|
-
cover_image: html.at_css('#main > div > div.main-detail > div.ttl-pac > a')['href'],
|
14
|
-
description: html.xpath('//*[@id="main"]/div/div[@class="main-detail"]/div[@class="ttl-comment"]/div[not(@class)]').text,
|
15
|
-
genres: specs['ジャンル:'].text,
|
16
|
-
maker: '変態紳士倶楽部',
|
17
|
-
movie_length: specs['収録時間:'].text,
|
18
|
-
release_date: specs['発売日:'].text,
|
19
|
-
sample_images: html.css('#main > div > div.main-detail > div.ttl-sample > img').map { |img| img['src'] },
|
20
|
-
series: specs['シリーズ:'].text,
|
21
|
-
thumbnail_image: html.at_css('#main > div > div.main-detail > div.ttl-pac > a > img')['src'],
|
22
|
-
title: html.css('#main > div > div.capt2').text,
|
23
|
-
}
|
24
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'opendmm/utils'
|
2
|
-
|
3
|
-
Dir[File.dirname(__FILE__) + '/search_engines/*.rb'].each do |file|
|
4
|
-
module_name = File.basename(file, '.rb').camelize
|
5
|
-
eval <<-ENGINE
|
6
|
-
|
7
|
-
module OpenDMM
|
8
|
-
module SearchEngine
|
9
|
-
module #{module_name}
|
10
|
-
include Site
|
11
|
-
#{File.read(file)}
|
12
|
-
def self.search(name)
|
13
|
-
self.product(name)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
ENGINE
|
20
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
base_uri 'www.aventertainments.com'
|
2
|
-
headers({
|
3
|
-
"User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36"
|
4
|
-
})
|
5
|
-
|
6
|
-
def self.search_url(name)
|
7
|
-
name = name.split(/(?<=[a-z])(?=\d)|[-_\s]/).join('-')
|
8
|
-
"/search_Products.aspx?keyword=#{CGI::escape(name)}"
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.product_url(name)
|
12
|
-
search_page = get_with_retry search_url(name)
|
13
|
-
return nil unless search_page
|
14
|
-
search_html = Utils.html_in_utf8 search_page
|
15
|
-
first_result = search_html.at_css('div.main-unit2 > table a')
|
16
|
-
first_result['href'] if first_result
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def self.parse_product_html(html)
|
22
|
-
specs = Utils.hash_by_split(html.xpath('//*[@id="TabbedPanels1"]/div/div[2]/div[1]//ol').text.split('|')).merge(
|
23
|
-
Utils.hash_by_split(html.xpath('//*[@id="titlebox"]/ul[3]/li').map(&:text)))
|
24
|
-
{
|
25
|
-
actresses: specs['主演女優'].split(','),
|
26
|
-
# brand: String
|
27
|
-
categories: html.xpath('//*[@id="TabbedPanels1"]/div/div[2]/div[2]//ol').map(&:text),
|
28
|
-
code: specs['商品番号'],
|
29
|
-
cover_image: html.at_css('#titlebox > div.list-cover > img')['src'].gsub('jacket_images', 'bigcover'),
|
30
|
-
description: html.css('#titlebox > div.border > p').text,
|
31
|
-
# directors: Array
|
32
|
-
# genres: Array
|
33
|
-
# label: String
|
34
|
-
maker: specs['スタジオ'],
|
35
|
-
movie_length: specs['収録時間'],
|
36
|
-
# page: String
|
37
|
-
release_date: Date.strptime(specs['発売日'], '%m/%d/%Y'),
|
38
|
-
# sample_images: Array
|
39
|
-
# scenes: Array
|
40
|
-
series: specs['シリーズ'],
|
41
|
-
# subtitle: String
|
42
|
-
# theme: String
|
43
|
-
thumbnail_image: html.at_css('#titlebox > div.list-cover > img')['src'],
|
44
|
-
title: html.css('#mini-tabet > h2').text,
|
45
|
-
}
|
46
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
base_uri 'www.dmm.co.jp'
|
2
|
-
|
3
|
-
def self.search_url(name, digit_len)
|
4
|
-
name = name.split(/(?<=[a-z])(?=\d)|[-_\s]/).map do |token|
|
5
|
-
token =~ /^\d+$/ ? token.rjust(digit_len, '0') : token
|
6
|
-
end.join
|
7
|
-
"/search/=/searchstr=#{CGI::escape(name)}"
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.product_url(name)
|
11
|
-
5.downto(3) do |len|
|
12
|
-
search_page = get_with_retry search_url(name, len)
|
13
|
-
next unless search_page
|
14
|
-
search_html = Utils.html_in_utf8 search_page
|
15
|
-
first_result = search_html.at_css('#list > li > div > p.tmb > a')
|
16
|
-
return first_result['href'] if first_result
|
17
|
-
end
|
18
|
-
nil
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.product_extra_info(name, url, page, html)
|
22
|
-
dmm_id = page.request.last_uri.to_s.split('/').last.split('=').last
|
23
|
-
if dmm_id =~ /\d*([a-z]+)0*(\d+)/i
|
24
|
-
dmm_id = "#{$1.upcase}-#{$2.rjust(3, '0')}"
|
25
|
-
end
|
26
|
-
{
|
27
|
-
code: dmm_id,
|
28
|
-
maker: 'DMM',
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def self.parse_product_html(html)
|
35
|
-
specs = Utils.hash_by_split(html.css('//div[@class="page-detail"]/table/tr/td[1]/table/tr').map(&:text))
|
36
|
-
{
|
37
|
-
actresses: ( specs['出演者'] || specs['名前'] ).split(/[\s\/]/),
|
38
|
-
cover_image: ( html.at_css('#sample-video > a')['href'] ||
|
39
|
-
html.at_css('#sample-video > img')['src'] ),
|
40
|
-
directors: specs['監督'].split,
|
41
|
-
genres: specs['ジャンル'].split,
|
42
|
-
label: specs['レーベル'],
|
43
|
-
maker: specs['メーカー'],
|
44
|
-
movie_length: specs['収録時間'],
|
45
|
-
release_date: (specs['商品発売日'] || specs['配信開始日']),
|
46
|
-
series: specs['シリーズ'],
|
47
|
-
thumbnail_image: html.at_css('#sample-video img')['src'],
|
48
|
-
title: html.css('#title').text,
|
49
|
-
}
|
50
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
base_uri 'www.javlibrary.com'
|
2
|
-
|
3
|
-
def self.search_url(name)
|
4
|
-
"/ja/vl_searchbyid.php?keyword=#{CGI::escape(name)}"
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.product_url(name)
|
8
|
-
search_page = get_with_retry search_url(name)
|
9
|
-
return nil unless search_page
|
10
|
-
if search_page.code == 302
|
11
|
-
url = search_page.headers['location']
|
12
|
-
else
|
13
|
-
search_html = Utils.html_in_utf8 search_page
|
14
|
-
links = search_html.css('#rightcolumn > div.videothumblist > div.videos > div.video > a')
|
15
|
-
result = links.detect do |link|
|
16
|
-
link.css('div.id').text == name
|
17
|
-
end
|
18
|
-
result ||= links.first
|
19
|
-
return nil unless result
|
20
|
-
url = result['href']
|
21
|
-
end
|
22
|
-
URI.join(search_page.request.last_uri, url).to_s
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.parse_product_html(html)
|
26
|
-
{
|
27
|
-
actresses: html.css('#video_cast .text span.cast span.star').map(&:text),
|
28
|
-
code: html.css('#video_id .text').text,
|
29
|
-
cover_image: html.at_css('#video_jacket > img')['src'],
|
30
|
-
directors: html.css('#video_director .text span.director').map(&:text),
|
31
|
-
genres: html.css('#video_genres .text span.genre').map(&:text),
|
32
|
-
label: html.css('#video_label .text').text,
|
33
|
-
maker: html.css('#video_maker .text').text,
|
34
|
-
movie_length: html.css('#video_length .text').text + ' minutes',
|
35
|
-
release_date: html.css('#video_date .text').text,
|
36
|
-
thumbnail_image: html.at_css('#video_jacket_img')['src'],
|
37
|
-
title: html.css('#video_title > h3').text.remove(html.css('#video_id .text').text),
|
38
|
-
}
|
39
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'pp'
|
2
|
-
|
3
|
-
base_uri 'www.mgstage.com'
|
4
|
-
cookies(adc: 1, coc: 1)
|
5
|
-
headers({
|
6
|
-
"User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36"
|
7
|
-
})
|
8
|
-
|
9
|
-
def self.product_url(name)
|
10
|
-
return "/ppv/video/#{name}/"
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def self.parse_product_html(html)
|
16
|
-
specs = Utils.hash_from_dl(html.css('div.content_detail_layout_01 > dl.spec_layout'))
|
17
|
-
{
|
18
|
-
actresses: specs['出演:'].css('a').map(&:text),
|
19
|
-
# actress_types: Array
|
20
|
-
# boobs: String
|
21
|
-
# brand: String
|
22
|
-
# categories: Array
|
23
|
-
code: specs['品番:'].text,
|
24
|
-
cover_image: html.at_css('a.enlarge_image')['href'],
|
25
|
-
description: html.css('#introduction_text > p.introduction').text,
|
26
|
-
# directors: Array
|
27
|
-
genres: specs['ジャンル:'].css('a').map(&:text),
|
28
|
-
# label: String
|
29
|
-
maker: specs['メーカー:'].text,
|
30
|
-
movie_length: specs['収録時間:'].text,
|
31
|
-
# page: String
|
32
|
-
release_date: specs['配信開始日:'].text,
|
33
|
-
sample_images: html.css('a.sample_imageN').map { |a| a['href'] },
|
34
|
-
# scenes: Array
|
35
|
-
series: specs['シリーズ名:'].text,
|
36
|
-
# subtitle: String
|
37
|
-
# theme: String
|
38
|
-
thumbnail_image: html.at_css('a.enlarge_image > img')['src'],
|
39
|
-
title: html.css('.title_detail_layout h1').text,
|
40
|
-
}
|
41
|
-
end
|
data/lib/opendmm/site.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
-
require 'httparty'
|
3
|
-
require 'opendmm/utils'
|
4
|
-
|
5
|
-
module OpenDMM
|
6
|
-
module Site
|
7
|
-
|
8
|
-
def self.included(klass)
|
9
|
-
klass.mattr_accessor :url_generators
|
10
|
-
klass.mattr_accessor :code_generators
|
11
|
-
klass.url_generators = Hash.new
|
12
|
-
klass.code_generators = Hash.new
|
13
|
-
|
14
|
-
klass.include HTTParty
|
15
|
-
klass.follow_redirects false
|
16
|
-
klass.default_timeout 10
|
17
|
-
|
18
|
-
klass.extend ClassMethods
|
19
|
-
end
|
20
|
-
|
21
|
-
module ClassMethods
|
22
|
-
def get_with_retry(url, limit = 5)
|
23
|
-
return nil unless url
|
24
|
-
get url
|
25
|
-
rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED => e
|
26
|
-
tries ||= 0
|
27
|
-
tries++
|
28
|
-
tries <= limit ? retry : raise
|
29
|
-
end
|
30
|
-
|
31
|
-
def register_product(matcher, url_generator, code_generator = '#{$1.upcase}-#{$2}')
|
32
|
-
url_generators[matcher] = '"' + url_generator + '"'
|
33
|
-
code_generators[matcher] = '"' + code_generator + '"'
|
34
|
-
end
|
35
|
-
|
36
|
-
def product_url(name)
|
37
|
-
url_generators.each do |matcher, url_generator|
|
38
|
-
if name =~ matcher
|
39
|
-
return eval url_generator
|
40
|
-
end
|
41
|
-
end
|
42
|
-
nil
|
43
|
-
end
|
44
|
-
|
45
|
-
def product_code(name)
|
46
|
-
code_generators.each do |matcher, code_generator|
|
47
|
-
if name =~ matcher
|
48
|
-
return eval code_generator
|
49
|
-
end
|
50
|
-
end
|
51
|
-
nil
|
52
|
-
end
|
53
|
-
|
54
|
-
def product_extra_info(name, url, page, html)
|
55
|
-
Hash.new
|
56
|
-
end
|
57
|
-
|
58
|
-
def product(name)
|
59
|
-
return nil unless name =~ /^[[:ascii:]]+$/
|
60
|
-
url = product_url name
|
61
|
-
page = get_with_retry url
|
62
|
-
return nil unless page && page.code == 200
|
63
|
-
html = Utils.html_in_utf8 page
|
64
|
-
html.css('script').remove
|
65
|
-
details = parse_product_html html
|
66
|
-
details[:code] ||= product_code name
|
67
|
-
details[:page] ||= page.request.last_uri.to_s
|
68
|
-
extra_info = product_extra_info(name, url, page, html)
|
69
|
-
extra_info.each do |k, v|
|
70
|
-
details[k] ||= v
|
71
|
-
end
|
72
|
-
details = Utils.finalize_details_hash details
|
73
|
-
%i(code cover_image maker page thumbnail_image title).each do |key|
|
74
|
-
return unless details[key]
|
75
|
-
end
|
76
|
-
details
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
data/lib/opendmm/utils.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/array/access'
|
2
|
-
require 'active_support/core_ext/array/grouping'
|
3
|
-
require 'active_support/core_ext/module/aliasing'
|
4
|
-
require 'active_support/core_ext/numeric/time'
|
5
|
-
require 'active_support/core_ext/string/filters'
|
6
|
-
require 'active_support/core_ext/string/starts_ends_with'
|
7
|
-
require 'chronic_duration'
|
8
|
-
require 'nokogiri'
|
9
|
-
|
10
|
-
class << Date
|
11
|
-
def parse_with_chinese_support(str)
|
12
|
-
case str
|
13
|
-
when /(\d{4})年(\d{1,2})月(\d{1,2})日/
|
14
|
-
return new($1.to_i, $2.to_i, $3.to_i)
|
15
|
-
when /(\d{2})年(\d{1,2})月(\d{1,2})日/
|
16
|
-
year = 2000 + $1.to_i
|
17
|
-
year -= 100 if year > Date.today.year
|
18
|
-
return new(year, $2.to_i, $3.to_i)
|
19
|
-
else
|
20
|
-
return parse_without_chinese_support(str)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
alias_method_chain :parse, :chinese_support
|
24
|
-
end
|
25
|
-
|
26
|
-
class << ChronicDuration
|
27
|
-
def parse_with_chinese_support(str)
|
28
|
-
case str
|
29
|
-
when /(\d+)\s*分\s*(\d+)\s*秒/
|
30
|
-
return $1.to_i.minutes + $2.to_i.seconds
|
31
|
-
when /(\d+)(\s*)分/
|
32
|
-
return $1.to_i.minutes
|
33
|
-
else
|
34
|
-
return parse_without_chinese_support(str)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
alias_method_chain :parse, :chinese_support
|
38
|
-
end
|
39
|
-
|
40
|
-
class NilClass
|
41
|
-
def method_missing(meth, *args, &block)
|
42
|
-
nil
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
module OpenDMM
|
47
|
-
module Utils
|
48
|
-
def self.hash_from_dl(dl)
|
49
|
-
dts = dl.css('dt').map(&:text).map(&:squish)
|
50
|
-
dds = dl.children.select do |node|
|
51
|
-
node.name == 'dt' || node.name == 'dd'
|
52
|
-
end.split do |node|
|
53
|
-
node.name == 'dt'
|
54
|
-
end[1..-1].map do |nodes|
|
55
|
-
node_set = Nokogiri::XML::NodeSet.new(dl.document)
|
56
|
-
nodes.each do |node|
|
57
|
-
node_set << node
|
58
|
-
end
|
59
|
-
node_set
|
60
|
-
end
|
61
|
-
Hash[dts.zip(dds)]
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.hash_by_split(array, delimiter = /[::]/)
|
65
|
-
array.map do |str|
|
66
|
-
slices = str.split(delimiter, 2).map(&:squish)
|
67
|
-
end.select do |pair|
|
68
|
-
pair.size == 2
|
69
|
-
end.to_h
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.html_in_utf8(content)
|
73
|
-
encoding = Nokogiri.HTML(content).encoding
|
74
|
-
content = content.encode('UTF-8', encoding, invalid: :replace, undef: :replace, replace: '')
|
75
|
-
Nokogiri.HTML content
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.finalize_details_hash(details)
|
79
|
-
details = details.squish_hard
|
80
|
-
details[:actresses] = details[:actresses].map do |actress|
|
81
|
-
actress.remove(/[\s\.]/)
|
82
|
-
end.sort if details[:actresses]
|
83
|
-
details[:cover_image] = join_url_if_relative(details[:page], details[:cover_image])
|
84
|
-
details[:thumbnail_image] = join_url_if_relative(details[:page], details[:thumbnail_image])
|
85
|
-
details[:sample_images] = details[:sample_images].map do |uri|
|
86
|
-
join_url_if_relative(details[:page], uri)
|
87
|
-
end if details[:sample_images]
|
88
|
-
details[:movie_length] = ChronicDuration.parse(details[:movie_length]).to_i if details[:movie_length]
|
89
|
-
details[:release_date] = Date.parse(details[:release_date]) if details[:release_date].instance_of? String
|
90
|
-
details.sort.to_h
|
91
|
-
end
|
92
|
-
|
93
|
-
def self.join_url_if_relative(page_url, image_url)
|
94
|
-
return nil unless image_url
|
95
|
-
image_url.start_with?('http') ? image_url : URI.join(page_url, image_url).to_s
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
class Object
|
101
|
-
def squish_hard
|
102
|
-
presence
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
class String
|
107
|
-
def squish_hard
|
108
|
-
squish.gsub(/^[\s-]*$/, '').presence
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
class Hash
|
113
|
-
def squish_hard
|
114
|
-
map do |k, v|
|
115
|
-
[k, v.squish_hard]
|
116
|
-
end.select do |k_v|
|
117
|
-
k_v.second.present?
|
118
|
-
end.to_h.presence
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
class Array
|
123
|
-
def squish_hard
|
124
|
-
map(&:squish_hard).select(&:present?).presence
|
125
|
-
end
|
126
|
-
end
|