morgoth-alexa 0.0.1
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.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +16 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/alexa.gemspec +51 -0
- data/lib/alexa/url_info.rb +62 -0
- data/lib/alexa.rb +21 -0
- data/test/alexa_test.rb +96 -0
- data/test/fixtures/polsl.xml +1275 -0
- data/test/test_helper.rb +16 -0
- metadata +75 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Wojciech Wnętrzak
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
= Alexa Web Information Service
|
2
|
+
|
3
|
+
== Usage
|
4
|
+
Alexa.url_info(:access_key_id => 'key', :secret_access_key => 'secret', :host => 'site.com')
|
5
|
+
# also you can specify option :response_group => 'Rank,ContactInfo' or any other valid group,
|
6
|
+
# see: http://docs.amazonwebservices.com/AlexaWebInfoService/2005-07-11/
|
7
|
+
# default response group takes all the available options
|
8
|
+
|
9
|
+
returns object with methods:
|
10
|
+
:xml_response, :rank, :data_url, :site_title, :site_description, :language_locale, :language_encoding,
|
11
|
+
:links_in_count, :keywords, :related_links, :speed_median_load_time, :speed_percentile,
|
12
|
+
:rank_by_country, :rank_by_city, :usage_statistics
|
13
|
+
|
14
|
+
== Copyright
|
15
|
+
|
16
|
+
Copyright (c) 2009 Wojciech Wnętrzak. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "alexa"
|
9
|
+
gem.summary = %Q{Alexa Web Information Service library}
|
10
|
+
gem.email = "w.wnetrzak@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/morgoth/alexa"
|
12
|
+
gem.authors = ["Wojciech Wnętrzak"]
|
13
|
+
gem.add_dependency('xml-simple')
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/*_test.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'rcov/rcovtask'
|
30
|
+
Rcov::RcovTask.new do |test|
|
31
|
+
test.libs << 'test'
|
32
|
+
test.pattern = 'test/**/*_test.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
task :rcov do
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
if File.exist?('VERSION.yml')
|
47
|
+
config = YAML.load(File.read('VERSION.yml'))
|
48
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
49
|
+
else
|
50
|
+
version = ""
|
51
|
+
end
|
52
|
+
|
53
|
+
rdoc.rdoc_dir = 'rdoc'
|
54
|
+
rdoc.title = "alexa #{version}"
|
55
|
+
rdoc.rdoc_files.include('README*')
|
56
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
57
|
+
end
|
58
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/alexa.gemspec
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{alexa}
|
5
|
+
s.version = "0.0.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Wojciech Wnętrzak"]
|
9
|
+
s.date = %q{2009-07-03}
|
10
|
+
s.email = %q{w.wnetrzak@gmail.com}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"LICENSE",
|
13
|
+
"README.rdoc"
|
14
|
+
]
|
15
|
+
s.files = [
|
16
|
+
".document",
|
17
|
+
".gitignore",
|
18
|
+
"LICENSE",
|
19
|
+
"README.rdoc",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"alexa.gemspec",
|
23
|
+
"lib/alexa.rb",
|
24
|
+
"lib/alexa/url_info.rb",
|
25
|
+
"test/alexa_test.rb",
|
26
|
+
"test/fixtures/polsl.xml",
|
27
|
+
"test/test_helper.rb"
|
28
|
+
]
|
29
|
+
s.homepage = %q{http://github.com/morgoth/alexa}
|
30
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
31
|
+
s.require_paths = ["lib"]
|
32
|
+
s.rubygems_version = %q{1.3.4}
|
33
|
+
s.summary = %q{Alexa Web Information Service library}
|
34
|
+
s.test_files = [
|
35
|
+
"test/alexa_test.rb",
|
36
|
+
"test/test_helper.rb"
|
37
|
+
]
|
38
|
+
|
39
|
+
if s.respond_to? :specification_version then
|
40
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
41
|
+
s.specification_version = 3
|
42
|
+
|
43
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
44
|
+
s.add_runtime_dependency(%q<xml-simple>, [">= 0"])
|
45
|
+
else
|
46
|
+
s.add_dependency(%q<xml-simple>, [">= 0"])
|
47
|
+
end
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<xml-simple>, [">= 0"])
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Alexa
|
2
|
+
class UrlInfo
|
3
|
+
RESPONSE_GROUP = "Rank,ContactInfo,AdultContent,Speed,Language,Keywords,OwnedDomains,LinksInCount,SiteData,RelatedLinks,RankByCountry,RankByCity,UsageStats"
|
4
|
+
attr_accessor :access_key_id, :secret_access_key, :host, :response_group, :xml_response,
|
5
|
+
:rank, :data_url, :site_title, :site_description, :language_locale, :language_encoding,
|
6
|
+
:links_in_count, :keywords, :related_links, :speed_median_load_time, :speed_percentile,
|
7
|
+
:rank_by_country, :rank_by_city, :usage_statistics
|
8
|
+
|
9
|
+
def initialize(options = {} )
|
10
|
+
@access_key_id = options[:access_key_id]
|
11
|
+
@secret_access_key = options[:secret_access_key]
|
12
|
+
@host = options[:host]
|
13
|
+
@response_group = options[:response_group] || RESPONSE_GROUP
|
14
|
+
end
|
15
|
+
|
16
|
+
def connect
|
17
|
+
action = "UrlInfo"
|
18
|
+
timestamp = ( Time::now ).utc.strftime("%Y-%m-%dT%H:%M:%S.000Z")
|
19
|
+
signature = generate_signature(secret_access_key, action, timestamp)
|
20
|
+
url = generate_url(action, access_key_id, signature, timestamp, response_group, host)
|
21
|
+
@xml_response = Net::HTTP.get(url)
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_xml(xml)
|
25
|
+
xml = XmlSimple.xml_in(xml.force_encoding(Encoding::UTF_8), 'ForceArray' => false)
|
26
|
+
@rank = xml['Response']['UrlInfoResult']['Alexa']['TrafficData']['Rank'].to_i
|
27
|
+
@data_url = xml['Response']['UrlInfoResult']['Alexa']['TrafficData']['DataUrl']['content']
|
28
|
+
@site_title = xml['Response']['UrlInfoResult']['Alexa']['ContentData']['SiteData']['Title']
|
29
|
+
@site_description = xml['Response']['UrlInfoResult']['Alexa']['ContentData']['SiteData']['Description']
|
30
|
+
@language_locale = xml['Response']['UrlInfoResult']['Alexa']['ContentData']['Language']['Locale']
|
31
|
+
@language_encoding = xml['Response']['UrlInfoResult']['Alexa']['ContentData']['Language']['Encoding']
|
32
|
+
@links_in_count = xml['Response']['UrlInfoResult']['Alexa']['ContentData']['LinksInCount'].to_i
|
33
|
+
@keywords = xml['Response']['UrlInfoResult']['Alexa']['ContentData']['Keywords']['Keyword']
|
34
|
+
@related_links = xml['Response']['UrlInfoResult']['Alexa']['Related']['RelatedLinks']['RelatedLink']
|
35
|
+
@speed_median_load_time = xml['Response']['UrlInfoResult']['Alexa']['ContentData']['Speed']['MedianLoadTime'].to_i
|
36
|
+
@speed_percentile = xml['Response']['UrlInfoResult']['Alexa']['ContentData']['Speed']['Percentile'].to_i
|
37
|
+
@rank_by_country = xml['Response']['UrlInfoResult']['Alexa']['TrafficData']['RankByCountry']['Country']
|
38
|
+
@rank_by_city = xml['Response']['UrlInfoResult']['Alexa']['TrafficData']['RankByCity']['City']
|
39
|
+
@usage_statistics = xml['Response']['UrlInfoResult']['Alexa']['TrafficData']['UsageStatistics']["UsageStatistic"]
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def generate_signature(secret_acces_key, action, timestamp)
|
45
|
+
Base64.encode64( OpenSSL::HMAC.digest( OpenSSL::Digest::Digest.new( "sha1" ), secret_access_key, action + timestamp)).strip
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_url(action, access_key_id, signature, timestamp, response_group, host)
|
49
|
+
url = URI.parse(
|
50
|
+
"http://awis.amazonaws.com/?" +
|
51
|
+
{
|
52
|
+
"Action" => action,
|
53
|
+
"AWSAccessKeyId" => access_key_id,
|
54
|
+
"Signature" => signature,
|
55
|
+
"Timestamp" => timestamp,
|
56
|
+
"ResponseGroup" => response_group,
|
57
|
+
"Url" => host
|
58
|
+
}.to_a.collect{|item| item.first + "=" + CGI::escape(item.last) }.join("&") # Put key value pairs into http GET format
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/alexa.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#/usr/bin/ruby
|
2
|
+
require "cgi"
|
3
|
+
require "base64"
|
4
|
+
require "openssl"
|
5
|
+
require "digest/sha1"
|
6
|
+
require "uri"
|
7
|
+
require "net/https"
|
8
|
+
require "xmlsimple"
|
9
|
+
require "time"
|
10
|
+
|
11
|
+
require 'alexa/url_info'
|
12
|
+
|
13
|
+
module Alexa
|
14
|
+
def self.url_info(options = {})
|
15
|
+
url_info = Alexa::UrlInfo.new(options)
|
16
|
+
xml = url_info.connect
|
17
|
+
url_info.parse_xml(xml)
|
18
|
+
url_info
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/test/alexa_test.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AlexaTest < Test::Unit::TestCase
|
4
|
+
context "Alexa::UrlInfo" do
|
5
|
+
setup do
|
6
|
+
@alexa = Alexa::UrlInfo.new(
|
7
|
+
:access_key_id => "12345678901234567890",
|
8
|
+
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF",
|
9
|
+
:host => "some.host"
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
should "Generate signature" do
|
14
|
+
signature = @alexa.send :generate_signature, @alexa.secret_access_key, "UrlInfo", '2009-07-03T07:22:24.000Z'
|
15
|
+
assert_equal "I1mPdBy+flhhzqqUaamNq9gq190=", signature
|
16
|
+
end
|
17
|
+
|
18
|
+
should "Generatee url" do
|
19
|
+
url = @alexa.send( :generate_url,
|
20
|
+
"UrlInfo",
|
21
|
+
@alexa.access_key_id,
|
22
|
+
"I1mPdBy+flhhzqqUaamNq9gq190=",
|
23
|
+
'2009-07-03T07:22:24.000Z',
|
24
|
+
"Rank,ContactInfo,AdultContent,Speed,Language,Keywords,OwnedDomains,LinksInCount,SiteData,RelatedLinks",
|
25
|
+
"heroku.com"
|
26
|
+
)
|
27
|
+
expected_uri = "/?Action=UrlInfo&AWSAccessKeyId=12345678901234567890&Signature=I1mPdBy%2BflhhzqqUaamNq9gq190%3D&Timestamp=2009-07-03T07%3A22%3A24.000Z&ResponseGroup=Rank%2CContactInfo%2CAdultContent%2CSpeed%2CLanguage%2CKeywords%2COwnedDomains%2CLinksInCount%2CSiteData%2CRelatedLinks&Url=heroku.com"
|
28
|
+
assert_equal expected_uri, url.request_uri
|
29
|
+
assert_equal "awis.amazonaws.com", url.host
|
30
|
+
end
|
31
|
+
|
32
|
+
context "should parse xml and" do
|
33
|
+
setup do
|
34
|
+
@xml = fixture_file('polsl.xml')
|
35
|
+
@alexa.parse_xml(@xml)
|
36
|
+
end
|
37
|
+
|
38
|
+
should "return rank" do
|
39
|
+
assert_equal 86020, @alexa.rank
|
40
|
+
end
|
41
|
+
|
42
|
+
should "return data url" do
|
43
|
+
assert_equal "polsl.pl", @alexa.data_url
|
44
|
+
end
|
45
|
+
|
46
|
+
should "return site title" do
|
47
|
+
assert_equal "Silesian University of Technology", @alexa.site_title
|
48
|
+
end
|
49
|
+
|
50
|
+
should "return site description" do
|
51
|
+
assert_equal "About the university, studies, faculties and departments, photo gallery.", @alexa.site_description
|
52
|
+
end
|
53
|
+
|
54
|
+
should "return language locale" do
|
55
|
+
assert_equal "pl-PL", @alexa.language_locale
|
56
|
+
end
|
57
|
+
|
58
|
+
should "return language encoding" do
|
59
|
+
assert_equal "iso-8859-2", @alexa.language_encoding
|
60
|
+
end
|
61
|
+
|
62
|
+
should "return links in count" do
|
63
|
+
assert_equal 281, @alexa.links_in_count
|
64
|
+
end
|
65
|
+
|
66
|
+
should "return keywords" do
|
67
|
+
assert_equal ["Polska", "Regionalne", "Gliwice"], @alexa.keywords
|
68
|
+
end
|
69
|
+
|
70
|
+
should "return related links" do
|
71
|
+
assert_equal 10, @alexa.related_links.count
|
72
|
+
end
|
73
|
+
|
74
|
+
should "return speed_median load time" do
|
75
|
+
assert_equal 266, @alexa.speed_median_load_time
|
76
|
+
end
|
77
|
+
|
78
|
+
should "return speed percentile" do
|
79
|
+
assert_equal 98, @alexa.speed_percentile
|
80
|
+
end
|
81
|
+
|
82
|
+
should "return rank by country" do
|
83
|
+
assert_equal 3, @alexa.rank_by_country.count
|
84
|
+
end
|
85
|
+
|
86
|
+
should "return rank by city" do
|
87
|
+
assert_equal 68, @alexa.rank_by_city.count
|
88
|
+
end
|
89
|
+
|
90
|
+
should "return usage statistics" do
|
91
|
+
assert_equal 4, @alexa.usage_statistics.count
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|