ex_ua 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +5 -2
- data/ex_ua.gemspec +4 -2
- data/lib/ex_ua/category.rb +51 -27
- data/lib/ex_ua/client.rb +30 -0
- data/lib/ex_ua/item.rb +16 -0
- data/lib/ex_ua/version.rb +1 -1
- data/lib/ex_ua.rb +4 -33
- data/spec/category_spec.rb +39 -2
- data/spec/client_spec.rb +15 -2
- data/spec/data/foreign_video_russia.html +237 -0
- data/spec/data/index.html +220 -0
- data/spec/data/ru_video.html +220 -0
- data/spec/data/video_test.html +423 -0
- data/spec/spec_helper.rb +17 -0
- metadata +61 -20
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5b80529d1a796a452c402596e0911c611cd09544
|
4
|
+
data.tar.gz: d576cc7c09db8586703340fce9e73bc9e2eca226
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 75a02afae964de65c138426ec6d792e1c18d8234353d796c8153d3d66c5d802eda8870c8ee0bb15126a07059b07d8462e6f06ad44a44a8cca9dc8b26a794fe1c
|
7
|
+
data.tar.gz: b276646a9b6d09b7505bc7f5f268cb4bfa82a73efe4ad8fa469e2e2c765abc0aa79614c893a6cfd7e81edd6110467b36e240c8b94bb92bc06ed568f00148d169
|
data/README.md
CHANGED
@@ -3,6 +3,8 @@ Description
|
|
3
3
|
|
4
4
|
ex_ua library gives you some API to access http://ex.ua/
|
5
5
|
|
6
|
+
Docs: http://rubydoc.info/github/Antti/ex_ua/master/frames
|
7
|
+
|
6
8
|
Install
|
7
9
|
=======
|
8
10
|
|
@@ -16,5 +18,6 @@ Example usage
|
|
16
18
|
client = ExUA::Client.new
|
17
19
|
base_categories = client.base_categories('ru') # Gives you array of all base categories for a given language
|
18
20
|
category = base_categories.first # Select first category (usually video)
|
19
|
-
sub_categories = category.categories
|
20
|
-
|
21
|
+
sub_categories = category.categories # Select sub-categories of a category
|
22
|
+
example_video_category = sub_categories.first.categories.first
|
23
|
+
download_items = example_video_category.items # Here you'll have an array of download items in a given category with #download_url
|
data/ex_ua.gemspec
CHANGED
@@ -19,6 +19,8 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
# specify any dependencies here; for example:
|
22
|
-
s.add_development_dependency "rspec"
|
23
|
-
s.
|
22
|
+
s.add_development_dependency "rspec", '>= 2.10.0'
|
23
|
+
s.add_development_dependency "rake", '>= 0.9.0'
|
24
|
+
s.add_runtime_dependency "httparty", '>= 0.10.0'
|
25
|
+
s.add_runtime_dependency "nokogiri", '>= 1.5.0'
|
24
26
|
end
|
data/lib/ex_ua/category.rb
CHANGED
@@ -1,14 +1,24 @@
|
|
1
|
+
# @author Andrii Dmytrenko
|
2
|
+
require 'cgi'
|
1
3
|
module ExUA
|
2
4
|
# Represents a category
|
5
|
+
# @example Usage
|
6
|
+
# #You usually get categories thru ExUA::Client object
|
7
|
+
# client = ExUA::Client.new
|
8
|
+
# categories = client.base_categories('ru')
|
9
|
+
# sub_categories = categories.first.categories
|
10
|
+
# items = sub_categories.first.categories.first.items
|
3
11
|
class Category
|
12
|
+
class NotFound < StandardError; end
|
4
13
|
attr_reader :id,:parent, :url
|
5
14
|
|
6
|
-
# @
|
7
|
-
# @
|
8
|
-
# @
|
9
|
-
def initialize(ex_ua,
|
10
|
-
@ex_ua
|
11
|
-
@
|
15
|
+
# @param[ExUA::Client] ex_ua client
|
16
|
+
# @param[Fixnum] id Category id
|
17
|
+
# @param[Hash] options
|
18
|
+
def initialize(ex_ua, options={})
|
19
|
+
@ex_ua = ex_ua
|
20
|
+
@id = options[:id]
|
21
|
+
@url = strip_url(options[:url]) || url_from_id(id)
|
12
22
|
@name = options.delete(:name)
|
13
23
|
@parent = options.delete(:parent)
|
14
24
|
end
|
@@ -22,30 +32,38 @@ module ExUA
|
|
22
32
|
end
|
23
33
|
|
24
34
|
# Canonical url
|
35
|
+
# @return [String]
|
25
36
|
def canonical_url
|
26
37
|
@canonical_url ||= page_content.root.xpath("//link[@rel='canonical']/@href").first.value
|
27
38
|
end
|
28
39
|
|
29
40
|
# Category name
|
41
|
+
# @return [String]
|
30
42
|
def name
|
31
43
|
@name ||= page_content.root.xpath("//meta[@name='title']/@content").first.value
|
32
44
|
end
|
33
45
|
|
34
46
|
# Category description
|
47
|
+
# @return [String]
|
35
48
|
def description
|
36
49
|
@description ||= page_content.root.xpath("//meta[@name='description']/@content").first.value
|
37
50
|
end
|
38
51
|
|
39
52
|
# Category picture
|
53
|
+
# @return [String] url for a picture
|
40
54
|
def picture
|
41
|
-
@picture ||=
|
55
|
+
@picture ||= (
|
56
|
+
pic = page_content.root.xpath("//link[@rel='image_src']/@href").first
|
57
|
+
pic && pic.value.split("?").first
|
58
|
+
)
|
42
59
|
end
|
43
60
|
|
44
61
|
# List of subcategories
|
62
|
+
# @return [Array<ExUA::Category>]
|
45
63
|
def categories
|
46
64
|
page_content.search('table.include_0 a b').map do |link|
|
47
|
-
if match = link.parent.attributes["href"].value.match(%r{/
|
48
|
-
Category.new(@ex_ua,
|
65
|
+
if match = link.parent.attributes["href"].value.match(%r{/(?<url>\d+)\?r=(?<r>\d+)})
|
66
|
+
Category.new(@ex_ua, parent: self, url: match['url'], name: link.text)
|
49
67
|
end
|
50
68
|
end.compact
|
51
69
|
end
|
@@ -61,45 +79,45 @@ module ExUA
|
|
61
79
|
end
|
62
80
|
|
63
81
|
# Next category
|
82
|
+
# @return [ExUA::Category]
|
64
83
|
def next
|
65
|
-
|
84
|
+
raise NotFound, "No link to a next category found" unless next?
|
85
|
+
Category.new(@ex_ua, id: self.id, url: next_url)
|
66
86
|
end
|
67
87
|
|
68
88
|
# Previous category
|
89
|
+
# @return [ExUA::Category]
|
69
90
|
def prev
|
70
|
-
|
91
|
+
raise NotFound, "No link to a previous category found" unless prev?
|
92
|
+
Category.new(@ex_ua, id: self.id, url: prev_url)
|
71
93
|
end
|
72
94
|
|
73
95
|
# Current page number
|
96
|
+
# @return [Fixnum]
|
74
97
|
def page
|
75
|
-
CGI.parse(URI.parse(@url).query||"")["p"].first || 0
|
98
|
+
CGI.parse(URI.parse(@url).query||"")["p"].first.to_i || 0
|
76
99
|
end
|
77
100
|
|
78
101
|
# Download items
|
102
|
+
# @return [Array<ExUA::Item>]
|
79
103
|
def items
|
80
104
|
table_rows = page_content.search('table.list tr')
|
81
105
|
table_rows.map do |tr|
|
82
106
|
tr.search("a[title!='']")
|
83
107
|
end.reject(&:empty?).map do |links|
|
84
|
-
Item.
|
85
|
-
links.each { |link|
|
86
|
-
case link.attributes["href"].value
|
87
|
-
when %r{^/get/}
|
88
|
-
item.title = link.attributes["title"].value
|
89
|
-
item.id = link.attributes["href"].value.match(%r{^/get/(\d+)})[1].to_i
|
90
|
-
when %r{^/load}
|
91
|
-
item.additional_servers||=[]
|
92
|
-
item.additional_servers << link.attributes["title"].value.match(%r{fs(\d+)})[1].to_i
|
93
|
-
end
|
94
|
-
}
|
95
|
-
end
|
108
|
+
Item.parse_links(links)
|
96
109
|
end
|
97
110
|
end
|
98
111
|
|
99
112
|
protected
|
100
113
|
|
114
|
+
def strip_url(url)
|
115
|
+
return unless url
|
116
|
+
url.sub(ExUA::BASE_URL, '')
|
117
|
+
end
|
118
|
+
|
101
119
|
def page_content
|
102
|
-
@page_content||=@ex_ua.
|
120
|
+
@page_content||=@ex_ua.get(url)
|
103
121
|
end
|
104
122
|
|
105
123
|
def url_from_id(id)
|
@@ -107,11 +125,17 @@ module ExUA
|
|
107
125
|
end
|
108
126
|
|
109
127
|
def next_url
|
110
|
-
@next_url||=
|
128
|
+
@next_url||=(
|
129
|
+
e = page_content.root.xpath("//link[@rel='next']/@href").first
|
130
|
+
e && e.value
|
131
|
+
)
|
111
132
|
end
|
112
133
|
|
113
134
|
def prev_url
|
114
|
-
@prev_url||=
|
135
|
+
@prev_url||=(
|
136
|
+
e = page_content.root.xpath("//link[@rel='prev']/@href").first
|
137
|
+
e && e.value
|
138
|
+
)
|
115
139
|
end
|
116
140
|
end
|
117
141
|
end
|
data/lib/ex_ua/client.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module ExUA
|
5
|
+
# Client for ExUA
|
6
|
+
# @example Usage
|
7
|
+
# client = ExUA::Client.new
|
8
|
+
# categories = client.base_categories('ru')
|
9
|
+
#
|
10
|
+
class Client
|
11
|
+
# List of available languages
|
12
|
+
# @return [Array<String>]
|
13
|
+
def available_languages
|
14
|
+
@available_langauges||=get('/').search('select[name=lang] option').inject({}){|acc,el| acc[el.attributes["value"].value]=el.text;acc}
|
15
|
+
end
|
16
|
+
|
17
|
+
# List of base categories for a given language
|
18
|
+
# @param[String] lang Language
|
19
|
+
# @example Usage
|
20
|
+
# client.base_categories('ru')
|
21
|
+
# @return [Array<ExUA::Category>]
|
22
|
+
def base_categories(lang)
|
23
|
+
ExUA::KNOWN_BASE_CATEGORIES.map{|cat| Category.new(self, url: "/#{lang}/#{cat}")}
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(url)
|
27
|
+
Nokogiri.parse(HTTParty.get("#{ExUA::BASE_URL}#{url}").body)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/ex_ua/item.rb
CHANGED
@@ -1,8 +1,24 @@
|
|
1
|
+
# @author Andrii Dmytrenko
|
1
2
|
module ExUA
|
2
3
|
# Download item
|
3
4
|
class Item < Struct.new(:id, :title, :additional_servers)
|
5
|
+
def self.parse_links(links)
|
6
|
+
self.new.tap do |item|
|
7
|
+
links.each { |link|
|
8
|
+
case link.attributes["href"].value
|
9
|
+
when %r{^/get/}
|
10
|
+
item.title = link.attributes["title"].value
|
11
|
+
item.id = link.attributes["href"].value.match(%r{^/get/(\d+)})[1].to_i
|
12
|
+
when %r{^/load}
|
13
|
+
item.additional_servers||=[]
|
14
|
+
item.additional_servers << link.attributes["title"].value.match(%r{fs(\d+)})[1].to_i
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
4
19
|
# Actual download url.
|
5
20
|
# You can add ?fs_id=server_id param to download form #additional_servers
|
21
|
+
# @return[String] download_url
|
6
22
|
def download_url
|
7
23
|
"#{ExUA::BASE_URL}#{url}"
|
8
24
|
end
|
data/lib/ex_ua/version.rb
CHANGED
data/lib/ex_ua.rb
CHANGED
@@ -1,39 +1,10 @@
|
|
1
|
-
|
2
|
-
BASE_URL='http://ex.ua'
|
3
|
-
end
|
1
|
+
# @author Andrii Dmytrenko
|
4
2
|
require "ex_ua/version"
|
3
|
+
require 'ex_ua/client'
|
5
4
|
require "ex_ua/item"
|
6
5
|
require "ex_ua/category"
|
7
|
-
require 'mechanize'
|
8
6
|
|
9
7
|
module ExUA
|
10
|
-
|
11
|
-
|
12
|
-
# client = ExUA::Client.new
|
13
|
-
# categories = client.base_categories('ru')
|
14
|
-
#
|
15
|
-
class Client
|
16
|
-
attr_reader :agent
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
@agent = Mechanize.new
|
20
|
-
end
|
21
|
-
|
22
|
-
def inspect
|
23
|
-
"#<#{self.class}>"
|
24
|
-
end
|
25
|
-
|
26
|
-
# List of available languages
|
27
|
-
def available_languages
|
28
|
-
@available_langauges||=@agent.get(BASE_URL).search('select[name=lang] option').inject({}){|acc,el| acc[el.attributes["value"].value]=el.text;acc}
|
29
|
-
end
|
30
|
-
|
31
|
-
# List of base categories for a given language
|
32
|
-
# @param[String] lang Language
|
33
|
-
# @example
|
34
|
-
# client.base_categories('ru')
|
35
|
-
def base_categories(lang)
|
36
|
-
%w[video audio images texts games software].map{|cat| Category.new(self, nil, url: "/#{lang}/#{cat}")}
|
37
|
-
end
|
38
|
-
end
|
8
|
+
BASE_URL='http://www.ex.ua'
|
9
|
+
KNOWN_BASE_CATEGORIES = %w[video audio images texts games software]
|
39
10
|
end
|
data/spec/category_spec.rb
CHANGED
@@ -1,4 +1,41 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
describe ExUA::Category do
|
3
|
-
|
4
|
-
|
3
|
+
context "general 1 page category" do
|
4
|
+
subject{ExUA::Category.new(client, url: 'ru_video.html')}
|
5
|
+
describe '#categories' do
|
6
|
+
it 'returns list of child categories' do
|
7
|
+
subject.categories.should be_kind_of(Array)
|
8
|
+
end
|
9
|
+
it 'has current category as a parent category for all childs' do
|
10
|
+
subject.categories.all?{|c| c.parent == subject}.should be_true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
its(:items){should_not be_nil}
|
14
|
+
its(:name){should eq("\u0412\u0438\u0434\u0435\u043E [RU - \u0440\u0443\u0441\u0441\u043A\u0438\u0439]")}
|
15
|
+
its(:description){should_not be_nil}
|
16
|
+
its(:canonical_url){should_not be_nil}
|
17
|
+
its(:next?){should be_false}
|
18
|
+
its(:prev?){should be_false}
|
19
|
+
end
|
20
|
+
context "general few pages category" do
|
21
|
+
subject{ExUA::Category.new(client, url: 'foreign_video_russia.html')}
|
22
|
+
describe '#next' do
|
23
|
+
it 'returns a category with same url, but different page number' do
|
24
|
+
subject.next.url.should eq('/ru/video/foreign?r=23775&p=1')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
describe '#prev' do
|
28
|
+
it 'returns a category with same url, but different page number' do
|
29
|
+
pending 'find a page with prev'
|
30
|
+
expect(subject.prev.url).to eq('')
|
31
|
+
end
|
32
|
+
it 'raises error when no prev url found' do
|
33
|
+
expect{subject.prev}.to raise_error(ExUA::Category::NotFound)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
context "item category" do
|
38
|
+
subject{ExUA::Category.new(client, url: 'video_test.html')}
|
39
|
+
its(:picture){should_not be_nil}
|
40
|
+
end
|
41
|
+
end
|
data/spec/client_spec.rb
CHANGED
@@ -1,4 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
describe ExUA::Client do
|
3
|
-
|
4
|
-
|
3
|
+
describe '#available_languages' do
|
4
|
+
it 'returns list of available languages' do
|
5
|
+
client.available_languages.should be_kind_of(Hash)
|
6
|
+
end
|
7
|
+
it 'includes known languages' do
|
8
|
+
known_languages = ["en", "ru", "uk"]
|
9
|
+
(client.available_languages.keys & known_languages).sort.should eq(known_languages)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
describe '#base_categories' do
|
13
|
+
it 'lists base categories for a language' do
|
14
|
+
client.base_categories("uk").should be_kind_of(Array)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|