require 'rubygems' require 'hpricot' require 'net/http' module RedfinApi module Base class << self # this method is often overridden for testing purposes def http_get(url) Net::HTTP.get_response(URI.parse(url)).body end def http_get_json(url) response = http_get(url) response = response.strip[2..-3] # ignore the /* and */ # puts "response = #{response}" require 'json' json_hash = JSON.parse(response) # TODO symbolize_keys! here json_hash end def fetch_address(url) response = http_get(url) doc = Hpricot(response) address = {} address[:address_line_1] = (doc/'#address_line_1')[0].to_plain_text rescue nil address[:city] = (doc/'#address_line_2 .locality')[0].to_plain_text rescue nil address[:state] = (doc/'#address_line_2 .region')[0].to_plain_text rescue nil address[:zip] = (doc/'#address_line_2 .postal-code')[0].to_plain_text rescue nil address[:pin] = extract_pin(response) address end def extract_pin(html) /Parcel Identification Number:\s*(\d{10,14})/.match(html)[1].strip end def query_location(address) url = "http://www.redfin.com/stingray/do/query-location?location=#{URI.encode(address)}" location = http_get_json(url) # we either get a postSalesBuildings element or listings element item = location['pastSalesBuildings'].not_nil? ? location['pastSalesBuildings'][0] : location['listings'][0] address = item['address'] hash = { :lat => item['point']['lat'].to_s, :lon => item['point']['long'].to_s, :number => address['number'], :street_name => address['streetName'], :street_type => address['streetType'], :unit => address['unitValue'], :address_line_1 => "#{address['number']} #{address['streetName']} #{address['streetType']}", :city => address['city'], :state => address['state'], :zip => address['zip'], } if location['pastSalesBuildings'].not_nil? hash[:property_id] = item['id'].to_s hash[:url] = construct_redfin_url_from_address(hash) else hash[:listing_id] = item['id'].to_s hash.merge!(gis_id_search(hash[:listing_id])) end hash end def construct_redfin_url_from_address(location) "http://www.redfin.com/#{location[:state]}/#{location[:city].gsub(' ','-')}/#{location[:number]}-#{location[:street_name].gsub(' ','-')}-#{location[:street_type]}-#{location[:zip]}/home/#{location[:property_id]}" end def gis_id_search(listing_id) url ="http://www.redfin.com/stingray/do/gis-id-search?listing_id=#{listing_id}" response = http_get(url) response = response.strip[3..-4] # ignore the /*( and )*/ require 'json' json_hash = JSON.parse(response) raise RuntimeError, "Failed to perform gis_id_search", json_hash if json_hash['resultCode' != 0] payload = json_hash['payload'][0] { :property_id => payload['property']['id'].to_s, :url => "http://www.redfin.com#{payload['URL']}", } end end end end