zillow4r 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +18 -0
- data/Gemfile.lock +23 -0
- data/README.md +69 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/zillow4r.rb +49 -0
- data/lib/zillow4r/api.rb +25 -0
- data/lib/zillow4r/api/base.rb +5 -0
- data/lib/zillow4r/api/chart.rb +12 -0
- data/lib/zillow4r/api/comps.rb +13 -0
- data/lib/zillow4r/api/deep_comps.rb +13 -0
- data/lib/zillow4r/api/deep_search_results.rb +12 -0
- data/lib/zillow4r/api/demographics.rb +38 -0
- data/lib/zillow4r/api/region_chart.rb +12 -0
- data/lib/zillow4r/api/region_children.rb +14 -0
- data/lib/zillow4r/api/search_results.rb +12 -0
- data/lib/zillow4r/api/updated_property_details.rb +52 -0
- data/lib/zillow4r/api/zestimate.rb +15 -0
- data/lib/zillow4r/models.rb +189 -0
- data/test/fixtures/chart.xml +19 -0
- data/test/fixtures/comps.xml +189 -0
- data/test/fixtures/deep_comps.xml +536 -0
- data/test/fixtures/deep_search_results.xml +102 -0
- data/test/fixtures/demographics.xml +849 -0
- data/test/fixtures/region_chart.xml +18 -0
- data/test/fixtures/region_children.xml +868 -0
- data/test/fixtures/search_results.xml +91 -0
- data/test/fixtures/updated_property_details.xml +75 -0
- data/test/fixtures/zestimate.xml +93 -0
- data/test/test_helper.rb +26 -0
- data/test/unit/chart_test.rb +18 -0
- data/test/unit/comps_test.rb +50 -0
- data/test/unit/deep_comps_test.rb +50 -0
- data/test/unit/deep_search_results_test.rb +28 -0
- data/test/unit/demographics_test.rb +39 -0
- data/test/unit/region_chart_test.rb +18 -0
- data/test/unit/region_children_test.rb +41 -0
- data/test/unit/search_results_test.rb +28 -0
- data/test/unit/updated_property_details_test.rb +65 -0
- data/test/unit/zestimate_test.rb +52 -0
- data/zillow4r.gemspec +105 -0
- 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'
|
data/lib/zillow4r/api.rb
ADDED
@@ -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,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,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,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,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
|