ex_ua 0.0.2 → 0.0.3
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 +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
|