seotracker 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/README.rdoc +2 -0
- data/VERSION +1 -1
- data/lib/seotracker/yandex/direct.rb +30 -0
- data/lib/seotracker/yandex.rb +31 -14
- data/lib/seotracker.rb +15 -0
- data/seotracker.gemspec +3 -2
- data/spec/lib/seotracker_spec.rb +34 -9
- metadata +10 -9
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class Seotracker::Yandex::Direct < Seotracker::Yandex
|
4
|
+
def special(word)
|
5
|
+
get_cookie
|
6
|
+
url = SEARCH_URL + "text=#{word}&p=0"
|
7
|
+
page = @agent.get(url, [], nil, {'cookie' => @cookie})
|
8
|
+
begin
|
9
|
+
texts = page.root.xpath('/html/body/div[3]/div/div/div/div/div[2]/div/h2/a')
|
10
|
+
hrefs = page.root.xpath('/html/body/div[3]/div/div/div/div/div/div/div/div/span')
|
11
|
+
|
12
|
+
# pre_result - массив вида ['text','text','text','url','url','url']
|
13
|
+
pre_result = []
|
14
|
+
texts.map { |t| pre_result << t.content.strip.squeeze("\n") }
|
15
|
+
hrefs.map { |h| pre_result << h.content.scan(/\w+\.\w+/).first unless h.content.scan(/\w+\.\w+/)== [] }
|
16
|
+
raise Seotracker::Yandex::Direct::Exception if pre_result.count != 6
|
17
|
+
|
18
|
+
# приводим pre_result к виду [{ad: text, url: url}}]
|
19
|
+
result = []
|
20
|
+
(0...3).to_a.each { |i| result << { ad: pre_result[i], url: pre_result[i + 3] } }
|
21
|
+
|
22
|
+
result
|
23
|
+
rescue Exception => e
|
24
|
+
debug "can't parse yandex direct:" + e.message
|
25
|
+
'error'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Seotracker::Yandex::Direct::Exception < Exception; end
|
data/lib/seotracker/yandex.rb
CHANGED
@@ -1,24 +1,41 @@
|
|
1
1
|
class Seotracker::Yandex < Seotracker
|
2
|
-
SEARCH_URL =
|
2
|
+
SEARCH_URL = 'http://yandex.ru/yandsearch?'
|
3
|
+
WORDSTAT_URL = 'http://wordstat.yandex.ru/?cmd=words&page=1&&geo=&text_geo=&text='
|
4
|
+
|
5
|
+
# получаем стастистику wordstat
|
6
|
+
# word - слово, по которому получаем статистику
|
7
|
+
def get_wordstat(word)
|
8
|
+
url = WORDSTAT_URL + word
|
9
|
+
get_cookie if @cookie.nil?
|
10
|
+
page = @agent.get(url, [], nil, {'cookie' => @cookie})
|
11
|
+
res = page.root.xpath('/html/body/form/table[2]/tbody/tr/td[4]/table/tbody/tr[3]/td/table/tbody/tr[2]/td[3]')
|
12
|
+
begin
|
13
|
+
res.first.content
|
14
|
+
rescue Exception => e
|
15
|
+
debug "can't get yandex wordstat:" + e.message
|
16
|
+
0
|
17
|
+
end
|
18
|
+
end
|
3
19
|
|
4
20
|
protected
|
5
21
|
|
6
22
|
def parse(word, start = 0)
|
7
23
|
start /= 10
|
24
|
+
get_cookie if @cookie.nil?
|
25
|
+
url = SEARCH_URL + "text=#{word}&p=#{start}"
|
26
|
+
page = @agent.get(url, [], nil, {'cookie' => @cookie})
|
8
27
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
28
|
+
begin
|
29
|
+
page.root.xpath('/html/body/div[3]/div/div/div[2]/ol/li/div/h2/a')
|
30
|
+
rescue Exception => e
|
31
|
+
debug "can't parse yandex:" + e.message
|
32
|
+
'error'
|
13
33
|
end
|
34
|
+
end
|
14
35
|
|
15
|
-
|
16
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
url = SEARCH_URL + "text=#{word}&p=#{start}"
|
20
|
-
|
21
|
-
page = @agent.get(url, [], nil, {'cookie' => @cookie})
|
22
|
-
page.root.xpath('/html/body/div[3]/div/div/div[2]/ol/li/div/h2/a')
|
36
|
+
def get_cookie
|
37
|
+
# у яндекса хитрая проверка на роботов
|
38
|
+
@agent.get('http://kiks.yandex.ru/su/')
|
39
|
+
@cookie = @agent.cookies.first
|
23
40
|
end
|
24
|
-
end
|
41
|
+
end
|
data/lib/seotracker.rb
CHANGED
@@ -11,6 +11,13 @@ class Seotracker
|
|
11
11
|
@agent.user_agent_alias = Seotracker::USER_AGENT
|
12
12
|
@agent.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
13
13
|
@agent.agent.http.retry_change_requests = true
|
14
|
+
|
15
|
+
@debug = true
|
16
|
+
|
17
|
+
if @debug
|
18
|
+
@log = Logger.new('log.txt')
|
19
|
+
#@agent.log = @log если надо логировать mechnize
|
20
|
+
end
|
14
21
|
end
|
15
22
|
|
16
23
|
def get_position(site, word)
|
@@ -18,6 +25,9 @@ class Seotracker
|
|
18
25
|
while (start < 200) && !found
|
19
26
|
links = parse(word, start)
|
20
27
|
start += RESULTS
|
28
|
+
|
29
|
+
break if links == 'error'
|
30
|
+
|
21
31
|
links.each do |l|
|
22
32
|
pos += 1
|
23
33
|
href = l.attribute('href').value.downcase
|
@@ -29,7 +39,12 @@ class Seotracker
|
|
29
39
|
end
|
30
40
|
found ? pos : 0
|
31
41
|
end
|
42
|
+
|
43
|
+
def debug(message)
|
44
|
+
@log.debug(message) if @debug
|
45
|
+
end
|
32
46
|
end
|
33
47
|
|
34
48
|
require 'seotracker/yandex'
|
49
|
+
require 'seotracker/yandex/direct'
|
35
50
|
require 'seotracker/google'
|
data/seotracker.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "seotracker"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["krivich ekaterina"]
|
12
|
-
s.date = "2012-04-
|
12
|
+
s.date = "2012-04-06"
|
13
13
|
s.description = "track sites position in google or yandex by keyword"
|
14
14
|
s.email = "kiote_the_one@mail.ru"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
"lib/seotracker.rb",
|
27
27
|
"lib/seotracker/google.rb",
|
28
28
|
"lib/seotracker/yandex.rb",
|
29
|
+
"lib/seotracker/yandex/direct.rb",
|
29
30
|
"seotracker.gemspec",
|
30
31
|
"spec/lib/seotracker_spec.rb",
|
31
32
|
"spec/spec_helper.rb"
|
data/spec/lib/seotracker_spec.rb
CHANGED
@@ -2,15 +2,23 @@
|
|
2
2
|
$LOAD_PATH << File.expand_path('../../', __FILE__)
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
+
def yandex_mocker(mock)
|
6
|
+
mock.expect(:get, mock, ['http://kiks.yandex.ru/su/'])
|
7
|
+
mock.expect(:get, mock, [Seotracker::Yandex::SEARCH_URL + "text=#{@word}&p=0", [], nil, {'cookie' => 'hi'}])
|
8
|
+
mock.expect(:cookies, ['hi'])
|
9
|
+
end
|
10
|
+
|
11
|
+
def common_mocker
|
12
|
+
mock = MiniTest::Mock.new
|
13
|
+
mock.expect(:root, mock)
|
14
|
+
mock.expect(:attribute, mock, %w/href/)
|
15
|
+
mock.expect(:value, "http://#{@site}")
|
16
|
+
end
|
17
|
+
|
5
18
|
describe Seotracker do
|
6
19
|
# общие моки, тут от природной лени несколько объектов используют один мок
|
7
20
|
# что может несколько напрягать в дальнейшем
|
8
|
-
|
9
|
-
mock = MiniTest::Mock.new
|
10
|
-
mock.expect(:root, mock)
|
11
|
-
mock.expect(:attribute, mock, %w/href/)
|
12
|
-
mock.expect(:value, "http://#{@site}")
|
13
|
-
end
|
21
|
+
|
14
22
|
|
15
23
|
before do
|
16
24
|
@site = 'serialmaniak.ru'
|
@@ -23,9 +31,7 @@ describe Seotracker do
|
|
23
31
|
|
24
32
|
# мокаем все неважное
|
25
33
|
mock = common_mocker
|
26
|
-
|
27
|
-
mock.expect(:get, mock, ['http://kiks.yandex.ru/su/'])
|
28
|
-
mock.expect(:cookies, ['hi'])
|
34
|
+
yandex_mocker(mock)
|
29
35
|
mock.expect(:xpath, [mock], %w\/html/body/div[3]/div/div/div[2]/ol/li/div/h2/a\)
|
30
36
|
|
31
37
|
@object.instance_variable_set(:@agent, mock)
|
@@ -52,4 +58,23 @@ describe Seotracker do
|
|
52
58
|
@object.get_position(@site, @word).must_be :>, 0
|
53
59
|
end
|
54
60
|
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe Seotracker::Yandex::Direct do
|
64
|
+
before do
|
65
|
+
@client = Seotracker::Yandex::Direct.new
|
66
|
+
@word = 'окна'
|
67
|
+
|
68
|
+
mock =common_mocker
|
69
|
+
yandex_mocker(mock)
|
70
|
+
mock.expect(:xpath, [mock, mock, mock], %w\/html/body/div[3]/div/div/div/div/div[2]/div/h2/a\)
|
71
|
+
mock.expect(:xpath, [mock, mock, mock], %w\/html/body/div[3]/div/div/div/div/div/div/div/div/span\)
|
72
|
+
mock.expect(:content, 'yandex.ru')
|
73
|
+
|
74
|
+
@client.instance_variable_set(:@agent, mock)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should get valid special' do
|
78
|
+
@client.special(@word).count.must_equal 3
|
79
|
+
end
|
55
80
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: seotracker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
16
|
-
requirement: &
|
16
|
+
requirement: &70312546860700 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70312546860700
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: mechanize
|
27
|
-
requirement: &
|
27
|
+
requirement: &70312546859880 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70312546859880
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: jeweler
|
38
|
-
requirement: &
|
38
|
+
requirement: &70312546859300 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70312546859300
|
47
47
|
description: track sites position in google or yandex by keyword
|
48
48
|
email: kiote_the_one@mail.ru
|
49
49
|
executables: []
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- lib/seotracker.rb
|
62
62
|
- lib/seotracker/google.rb
|
63
63
|
- lib/seotracker/yandex.rb
|
64
|
+
- lib/seotracker/yandex/direct.rb
|
64
65
|
- seotracker.gemspec
|
65
66
|
- spec/lib/seotracker_spec.rb
|
66
67
|
- spec/spec_helper.rb
|
@@ -79,7 +80,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
80
|
version: '0'
|
80
81
|
segments:
|
81
82
|
- 0
|
82
|
-
hash: -
|
83
|
+
hash: -713848669405107154
|
83
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
85
|
none: false
|
85
86
|
requirements:
|