zillow4r 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/Gemfile +18 -0
  2. data/Gemfile.lock +23 -0
  3. data/README.md +69 -0
  4. data/Rakefile +53 -0
  5. data/VERSION +1 -0
  6. data/lib/zillow4r.rb +49 -0
  7. data/lib/zillow4r/api.rb +25 -0
  8. data/lib/zillow4r/api/base.rb +5 -0
  9. data/lib/zillow4r/api/chart.rb +12 -0
  10. data/lib/zillow4r/api/comps.rb +13 -0
  11. data/lib/zillow4r/api/deep_comps.rb +13 -0
  12. data/lib/zillow4r/api/deep_search_results.rb +12 -0
  13. data/lib/zillow4r/api/demographics.rb +38 -0
  14. data/lib/zillow4r/api/region_chart.rb +12 -0
  15. data/lib/zillow4r/api/region_children.rb +14 -0
  16. data/lib/zillow4r/api/search_results.rb +12 -0
  17. data/lib/zillow4r/api/updated_property_details.rb +52 -0
  18. data/lib/zillow4r/api/zestimate.rb +15 -0
  19. data/lib/zillow4r/models.rb +189 -0
  20. data/test/fixtures/chart.xml +19 -0
  21. data/test/fixtures/comps.xml +189 -0
  22. data/test/fixtures/deep_comps.xml +536 -0
  23. data/test/fixtures/deep_search_results.xml +102 -0
  24. data/test/fixtures/demographics.xml +849 -0
  25. data/test/fixtures/region_chart.xml +18 -0
  26. data/test/fixtures/region_children.xml +868 -0
  27. data/test/fixtures/search_results.xml +91 -0
  28. data/test/fixtures/updated_property_details.xml +75 -0
  29. data/test/fixtures/zestimate.xml +93 -0
  30. data/test/test_helper.rb +26 -0
  31. data/test/unit/chart_test.rb +18 -0
  32. data/test/unit/comps_test.rb +50 -0
  33. data/test/unit/deep_comps_test.rb +50 -0
  34. data/test/unit/deep_search_results_test.rb +28 -0
  35. data/test/unit/demographics_test.rb +39 -0
  36. data/test/unit/region_chart_test.rb +18 -0
  37. data/test/unit/region_children_test.rb +41 -0
  38. data/test/unit/search_results_test.rb +28 -0
  39. data/test/unit/updated_property_details_test.rb +65 -0
  40. data/test/unit/zestimate_test.rb +52 -0
  41. data/zillow4r.gemspec +105 -0
  42. metadata +183 -0
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem "nokogiri"
6
+
7
+ # Add dependencies to develop your gem here.
8
+ # Include everything needed to run rake, tests, features, etc.
9
+ group :development do
10
+ gem "mocha"
11
+ gem "bundler", "~> 1.0.0"
12
+ gem "jeweler", "~> 1.5.1"
13
+ gem "rcov", ">= 0"
14
+ end
15
+
16
+ group :test do
17
+ gem "mocha"
18
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,23 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.5.1)
6
+ bundler (~> 1.0.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ mocha (0.9.10)
10
+ rake
11
+ nokogiri (1.4.4)
12
+ rake (0.8.7)
13
+ rcov (0.9.9)
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ bundler (~> 1.0.0)
20
+ jeweler (~> 1.5.1)
21
+ mocha
22
+ nokogiri
23
+ rcov
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ Zillow4r
2
+ --------
3
+
4
+ Simple ruby interface for the [Zillow API](http://www.zillow.com/howto/api/APIOverview.htm).
5
+
6
+ ### Documentation & Requirements
7
+ * Nokogiri
8
+
9
+ ### Supported API Calls
10
+
11
+ As of version 0.1.0, we support the following API calls:
12
+
13
+ * [GetZestimate](http://www.zillow.com/howto/api/GetZestimate.htm)
14
+ * [GetSearchResults](http://www.zillow.com/howto/api/GetSearchResults.htm)
15
+ * [GetChart](http://www.zillow.com/howto/api/GetChart.htm)
16
+ * [GetComps](http://www.zillow.com/howto/api/GetComps.htm)
17
+ * [GetDeepComps](http://www.zillow.com/howto/api/GetDeepComps.htm)
18
+ * [GetDeepSearchResults](http://www.zillow.com/howto/api/GetDeepSearchResults.htm)
19
+ * [GetUpdatedPropertyDetails](http://www.zillow.com/howto/api/GetUpdatedPropertyDetails.htm)
20
+ * [GetDemographics](http://www.zillow.com/howto/api/GetDemographics.htm)
21
+ * [GetRegionChildren](http://www.zillow.com/howto/api/GetRegionChildren.htm)
22
+ * [GetRegionChart](http://www.zillow.com/howto/api/GetRegionChart.html)
23
+
24
+ To make these calls, you call the module method `Zillow4r.fetch_[name]` where name is the underscored
25
+ api call name without the "Get". For example, if you wanted to call the GetDeepSearchResults
26
+ API, call `Zillow4r.fetch_deep_search_results` with the search parameters specified by the API.
27
+
28
+ Note: Zillow4r will automatically add your ZWSID to the API request.
29
+
30
+ ### Examples
31
+
32
+ Basic usage:
33
+
34
+ require 'rubygems'
35
+ require 'zillow4r'
36
+
37
+ Zillow4r.zws_id = 'YOUR_API_KEY'
38
+
39
+ response = Zillow4r.fetch_updated_property_details(:zpid => 123456)
40
+ response.class
41
+ => Zillow4r::Api::UpdatedPropertyDetails
42
+
43
+ response = Zillow4r.fetch_search_results(:address => "2114 Bigelow Ave", :citystatezip => "Seattle, WA")
44
+ response.class
45
+ => Zillow4r::Api::SearchResults
46
+ response.results.class
47
+ => Array
48
+ response.results.first.class
49
+ => Zillow4r::Property
50
+
51
+ ### Models
52
+
53
+ Zillow4r uses several intermediate data models which represent repeated data structures contained within
54
+ Zillow's xml. These include:
55
+
56
+ * Zillow4r::Address
57
+ * Zillow4r::Links
58
+ * Zillow4r::Images
59
+ * Zillow4r::Region
60
+ * Zillow4r::Property
61
+ * Zillow4r::Posting
62
+ * Zillow4r::Zestimate
63
+ * Zillow4r::ComparableProperty
64
+
65
+ These models define the data that they contain through their position within the xml data.
66
+
67
+ ### Testing
68
+
69
+ Test cases are mocked using the sample API output provided for each API call in the documentation from Zillow.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "zillow4r"
16
+ gem.homepage = "http://github.com/chingor13/zillow4r"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Simple ruby interface for the Zillow API}
19
+ gem.description = %Q{Simple ruby interface for the Zillow API. See http://www.zillow.com/howto/api/APIOverview.htm}
20
+ gem.email = "ching.jeff@gmail.com"
21
+ gem.authors = ["Jeff Ching"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ test.libs << 'lib' << 'test'
32
+ test.pattern = 'test/**/*_test.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |test|
38
+ test.libs << 'test'
39
+ test.pattern = 'test/**/*_test.rb'
40
+ test.verbose = true
41
+ end
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "zillow4r #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/zillow4r.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'open-uri'
3
+ require 'nokogiri'
4
+ require 'cgi'
5
+ module Zillow4r
6
+
7
+ HTTP_USER_AGENT = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1"
8
+ HTTP_ACCEPT = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
9
+ WEB_API_HOST = "www.zillow.com"
10
+ WEB_API_PORT = 80
11
+
12
+ class << self
13
+ attr_accessor :zws_id
14
+
15
+ def method_missing(a, *args)
16
+ if match = a.to_s.match(/^fetch_(.*)$/)
17
+ self.fetch(match[1], args[0])
18
+ else
19
+ super(a, *args)
20
+ end
21
+ end
22
+
23
+ def fetch(type, params = {})
24
+ klass = get_class(type)
25
+ path = build_path(klass, params)
26
+ url = "http://" + WEB_API_HOST + path
27
+ klass.new(open(url).read)
28
+ end
29
+
30
+ def build_path(klass, params)
31
+ p = ["zws-id=#{Zillow4r.zws_id}"]
32
+ params.each do |key,value|
33
+ p << "#{key}=#{CGI.escape(value.to_s)}"
34
+ end
35
+ "#{klass.path}?#{p.join('&')}"
36
+ end
37
+
38
+ private
39
+
40
+ def get_class(type)
41
+ class_name = type.split("_").map{|word| word[0..0].upcase + word[1..word.length]}.join("")
42
+ Zillow4r::Api.const_get(class_name)
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ require 'zillow4r/models.rb'
49
+ require 'zillow4r/api.rb'
@@ -0,0 +1,25 @@
1
+ module Zillow4r
2
+ module Api
3
+ class Base < Zillow4r::Base
4
+ def self.path
5
+ raise "Need to set path for child class"
6
+ end
7
+
8
+ int_point "response_code", "message code", "data"
9
+ text_point "response_message", "message text", "data"
10
+
11
+ def data_error?
12
+ response_code.nil? || response_code > 500
13
+ end
14
+
15
+ def error?
16
+ response_code.nil? || response_code > 0
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ Dir.glob(File.dirname(__FILE__) + "/api/*.rb").each do |file|
23
+ require file
24
+ end
25
+
@@ -0,0 +1,5 @@
1
+ require 'nokogiri'
2
+ module Zillow4r
3
+ module Api
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ module Zillow4r
2
+ module Api
3
+ class Chart < Zillow4r::Api::Base
4
+ text_point :chart_url, "response url", :data
5
+
6
+ def self.path
7
+ "/webservice/GetChart.htm"
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Zillow4r
2
+ module Api
3
+ class Comps < Zillow4r::Api::Base
4
+ object_point :principal, "response properties principal", :data, Zillow4r::Property
5
+ array_point :comparables, "response/properties/comparables", :data, Zillow4r::ComparableProperty
6
+
7
+ def self.path
8
+ "/webservice/GetComps.htm"
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Zillow4r
2
+ module Api
3
+ class DeepComps < Zillow4r::Api::Base
4
+ object_point :principal, "response properties principal", :data, Zillow4r::Property
5
+ array_point :comparables, "response/properties/comparables", :data, Zillow4r::ComparableProperty
6
+
7
+ def self.path
8
+ "/webservice/GetDeepComps.htm"
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Zillow4r
2
+ module Api
3
+ class DeepSearchResults < Zillow4r::Api::Base
4
+ array_point :results, "response/results", :data, Zillow4r::Property
5
+
6
+ def self.path
7
+ "/webservice/GetDeepSearchResults.htm"
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,38 @@
1
+ module Zillow4r
2
+ module Api
3
+ class Demographics < Zillow4r::Api::Base
4
+ object_point :region, "response region", :data, Zillow4r::Region
5
+ object_point :links, "response links", :data, Zillow4r::Links
6
+
7
+ # intermediate points
8
+ data_point :people_data_node, ["response pages", {"name" => "People"}, "tables", {"name" => "People Data"}, "data"], :data
9
+ data_point :owners_data_node, ["response pages", {"name" => "Homes & Real Estate"}, "tables", {"name" => "Census Summary-Occupancy"}, "data"], "data"
10
+
11
+ # city demographic values
12
+ float_point :city_median_age, [{"name" => "Median Age"}, "values city value"], :people_data_node
13
+ float_point :city_median_household_income, [{"name" => "Median Household Income"}, "values city value"], :people_data_node
14
+ float_point :city_average_household_size, [{"name" => "Average Household Size"}, "values city value"], :people_data_node
15
+ float_point :city_percent_of_homes_with_kids, [{"name" => "Homes With Kids"}, "values city value"], :people_data_node
16
+
17
+ # neighborhood demographic values
18
+ float_point :neighborhood_median_age, [{"name" => "Median Age"}, "values neighborhood value"], :people_data_node
19
+ float_point :neighborhood_median_household_income, [{"name" => "Median Household Income"}, "values neighborhood value"], :people_data_node
20
+ float_point :neighborhood_average_household_size, [{"name" => "Average Household Size"}, "values neighborhood value"], :people_data_node
21
+ float_point :neighborhood_percent_of_homes_with_kids, [{"name" => "Homes With Kids"}, "values neighborhood value"], :people_data_node
22
+
23
+ # nation demographic values
24
+ float_point :nation_median_age, [{"name" => "Median Age"}, "values nation value"], :people_data_node
25
+ float_point :nation_median_household_income, [{"name" => "Median Household Income"}, "values nation value"], :people_data_node
26
+ float_point :nation_average_household_size, [{"name" => "Average Household Size"}, "values nation value"], :people_data_node
27
+ float_point :nation_percent_of_homes_with_kids, [{"name" => "Homes With Kids"}, "values nation value"], :people_data_node
28
+
29
+ float_point :percent_owners, [{"name" => "Own"}, "value"], :owners_data_node
30
+ float_point :percent_renters, [{"name" => "Rent"}, "value"], :owners_data_node
31
+
32
+ def self.path
33
+ "/webservice/GetDemographics.htm"
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,12 @@
1
+ module Zillow4r
2
+ module Api
3
+ class RegionChart < Zillow4r::Api::Base
4
+ text_point :chart_url, "response url", :data
5
+
6
+ def self.path
7
+ "/webservice/GetRegionChart.htm"
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module Zillow4r
2
+ module Api
3
+ class RegionChildren < Zillow4r::Api::Base
4
+ object_point :region, "response/region", :data, Zillow4r::Region
5
+ text_point :subregion_type, "response subregiontype", :data
6
+ array_point :children, "response/list", :data, Zillow4r::Region
7
+
8
+ def self.path
9
+ "/webservice/GetRegionChildren.htm"
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ module Zillow4r
2
+ module Api
3
+ class SearchResults < Zillow4r::Api::Base
4
+ array_point :results, "response/results", :data, Zillow4r::Property
5
+
6
+ def self.path
7
+ "/webservice/GetSearchResults.htm"
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,52 @@
1
+ module Zillow4r
2
+ module Api
3
+ class UpdatedPropertyDetails < Zillow4r::Api::Base
4
+ int_point :zpid, "response zpid", :data
5
+
6
+ # page views
7
+ int_point :page_view_count_month, "response pageviewcount currentmonth", :data
8
+ int_point :page_view_count_total, "response pageviewcount total", :data
9
+
10
+ object_point :address, "response address", :data, Zillow4r::Address
11
+ object_point :posting, "response posting", :data, Zillow4r::Posting
12
+
13
+ # price
14
+ int_point :price, "response price", :data
15
+ attribute_point :price_currency, "response price", :data, "currency"
16
+
17
+ object_point :links, "response links", :data, Zillow4r::Links
18
+ object_point :images, "response images image", :data, Zillow4r::Images
19
+
20
+ # facts
21
+ data_point :facts_data_node, "response editedfacts", :data
22
+ text_point :use_code, "usecode", :facts_data_node
23
+ int_point :bedrooms, "bedrooms", :facts_data_node
24
+ float_point :bathrooms, "bathrooms", :facts_data_node
25
+ int_point :finished_sq_ft, "finishedsqft", :facts_data_node
26
+ int_point :lot_sq_ft, "lotsizesqft", :facts_data_node
27
+ int_point :year_built, "yearbuilt", :facts_data_node
28
+ int_point :year_updated, "yearupdated", :facts_data_node
29
+ int_point :floors, "numfloors", :facts_data_node
30
+ text_point :basement, "basement", :facts_data_node
31
+ text_point :roof, "roof", :facts_data_node
32
+ text_point :view, "view", :facts_data_node
33
+ text_point :parking_type, "parkingtype", :facts_data_node
34
+ text_point :heating_sources, "heatingsources", :facts_data_node
35
+ text_point :heating_system, "heatingsystem", :facts_data_node
36
+ text_point :appliances, "appliances", :facts_data_node
37
+ text_point :floor_covering, "floorcovering", :facts_data_node
38
+ text_point :rooms, "rooms", :facts_data_node
39
+
40
+ # general info
41
+ text_point :home_description, "response homedescription", :data
42
+ text_point :neighborhood, "response neighborhood", :data
43
+ text_point :school_district, "response schooldistrict", :data
44
+ text_point :elementary_school, "response elementaryschool", :data
45
+ text_point :middle_school, "response middleschool", :data
46
+
47
+ def self.path
48
+ "/webservice/GetUpdatedPropertyDetails.htm"
49
+ end
50
+ end
51
+ end
52
+ end