Table of Contents
Streamlining Real Estate Research
In today’s fast-paced world, where time is of the essence, finding the perfect home can be daunting. It often involves browsing multiple platforms, gathering data, and cross-referencing information. However, thanks to the power of automation and the integration of popular platforms like Zillow and Google Maps, the process of researching real estate has become more efficient and streamlined. In this blog post, we introduce a Telegram bot that fetches data from Zillow and provides distance information from the Google Maps API, making house hunting a breeze.
The Power of Zillow:
Zillow, one of the leading online real estate marketplaces, provides a wealth of information about properties for sale or rent. From property details and pricing to historical data and local amenities, Zillow offers a comprehensive platform for real estate research. Our Telegram bot leverages the power of Zillow by extracting key data from a given Zillow link.
Integrating Google Maps API:
While Zillow provides valuable property information, location plays a crucial role in any real estate decision. To address this, our Telegram bot utilizes the Google Maps API to calculate distances and provide accurate information about the surrounding area. With the integration of Google Maps, users can easily determine the proximity of a property to schools, parks, shopping centers, and other important amenities.
Using a Telegram Bot:
To utilize our Telegram bot, simply provide a Zillow link for the desired property. The bot will automatically fetch relevant information, such as property details, pricing and other details, from Zillow’s website. Additionally, it will use the Google Maps API to determine the distance between the property and various points of interest.
Benefits and Features:
Time-saving
The bot eliminates the need for manual research and aggregation of data from multiple sources, saving users valuable time.
Comprehensive property details
By fetching data directly from Zillow, the bot provides a comprehensive overview of the property, including square footage, the number of bedrooms and bathrooms, and additional information.
Proximity analysis
The Google Maps integration enables users to understand the property’s location better and assess its proximity to key points of interest.
Convenient access
With the Telegram bot, users can access property information and distance calculations from the comfort of their smartphones or desktops, making it easily accessible on the go.
Steps
- Install the dependencies.
requirements.txt
1 2 3 4 |
requests~=2.31.0 beautifulsoup4~=4.12.2 telepot~=12.7 PyYAML~=6.0 |
1 |
pip install -r requirements.txt |
2. Create a config.yaml file and add following lines to the file. Don’t forget to replace <telegram_bot_token> and <google_api_token>
config.yaml
1 2 |
bot_token: <telegram_bot_token> api_key: <google_api_key> |
3. Create a file named config_util.py, a script to read config.yaml
config_util.py
1 2 3 4 5 6 7 8 9 10 11 |
import yaml with open('./config.yaml') as f: config_yaml = yaml.load(f, Loader=yaml.FullLoader) def read_google_api_key(): return config_yaml['api_key'] def read_telegram_bot_token(): return config_yaml['bot_token'] |
4. Create a file named zillow_client.py. It uses beautiful soup lib to parse the content fetched using requests lib.
zillow_client.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
from bs4 import BeautifulSoup import requests import json class ZillowClient: def __init__(self): pass @staticmethod def fetch(url): req_headers = { 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'en-US,en;q=0.8', 'upgrade-insecure-requests': '1', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.57' } raw_dict = {} try: with requests.Session() as s: r = s.get(url, headers=req_headers) soup = BeautifulSoup(r.content, 'html.parser') details = soup.find(id="hdpApolloPreloadedData").text raw_dict = json.loads(details)['apiCache'] raw_dict = json.loads(raw_dict) except Exception as e: print(e) return raw_dict @staticmethod def process_fetched_content(raw_dictionary=None): new_dict = {} if raw_dictionary is not None: for k in raw_dictionary.keys(): # Add property details if k.startswith('VariantQuery{"zpid":'): property = raw_dictionary.get(k).get('property', None) # print(property) new_dict.update(property) # get zestimate, bedrooms, bathrooms, yearBuilt, etc. if k.startswith('ForSaleShopperPlatformFullRenderQuery{"zpid"'): property = raw_dictionary.get(k).get('property', None) new_dict['zestimate'] = property['zestimate'] new_dict['bedrooms'] = property['bedrooms'] new_dict['bathrooms'] = property['bathrooms'] new_dict['yearBuilt'] = property['yearBuilt'] new_dict['comps'] = property['comps'] new_dict['taxHistory'] = property['taxHistory'] new_dict['priceHistory'] = property['priceHistory'] new_dict['description'] = property['description'] return new_dict if __name__ == "__main__": zillow_client = ZillowClient() # Quick Test raw = zillow_client.fetch( "https://www.zillow.com/homedetails/3-Prusakowski-Blvd-Parlin-NJ-08859/64487996_zpid/?utm_campaign=iosappmessage&utm_medium=referral&utm_source=txtshare") processed = zillow_client.process_fetched_content(raw) print(processed) |
5. Create a file named google_client.py to call Google’s Distance Matrix API to determine the distance between the origin and destination.
google_client.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
import requests import config_util class GoogleClient: def __init__(self): self.api_key = config_util.read_google_api_key() def get_distance(self, origin, destination): new_dict = {} try: url = f"https://maps.googleapis.com/maps/api/distancematrix/json?origins={origin}&destinations={destination}&key={self.api_key}" response = requests.get(url) data = response.json() print(data) # conversion factor # to convert from kilometers to miles conv_fac = 0.621371 if data['status'] == 'OK': distance = data['rows'][0]['elements'][0]['distance']['value'] miles = distance / 1000.0 * conv_fac new_dict['distance'] = f"{miles} miles" duration = data['rows'][0]['elements'][0]['duration']['text'] new_dict['duration'] = f"{duration}" except Exception as e: print(e) return new_dict def get_travel_distance(self, origin): # you can add more destinations to this dictionary destinations = { "metropark": { "address": "100 Middlesex Essex Turnpike, Iselin, NJ 08830" } } for key in destinations.keys(): new_dict = self.get_distance(origin, destinations[key]['address']) destinations[key].update(new_dict) return destinations if __name__ == "__main__": google_client = GoogleClient() # Provide the origin and destination origin = "3 Prusakowski Blvd, Parlin, NJ 08859" # destination = "100 Middlesex Essex Turnpike, Iselin, NJ 08830" # Get the travel distance # distance = google_client.get_distance(origin, destination) # print(f"The estimated travel distance from {origin} to {destination} is {distance}.") lst = google_client.get_travel_distance(origin) print(lst) |
6. Create a file named formatter.py to create a formatted message to be sent as a response to a query by a user.
formatter.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# to format the message class Formatter: def get_formatted_info(self, processed_dict): message = "" if processed_dict: if 'address' in processed_dict: message += f"Address: {processed_dict['address']}\n" if 'homeType' in processed_dict: message += f"{processed_dict['homeType']} |" if 'price' in processed_dict: message += f" ${processed_dict['price']} |" if 'yearBuilt' in processed_dict: message += f" {processed_dict['yearBuilt']} |" if 'bedrooms' in processed_dict: message += f" {processed_dict['bedrooms']}B |" if 'bathrooms' in processed_dict: message += f" {processed_dict['bathrooms']}BA\n" if 'zestimate' in processed_dict: message += f" Z${processed_dict['zestimate']} |" if 'daysOnZillow' in processed_dict: message += f" {processed_dict['daysOnZillow']}D\n" if 'metropark' in processed_dict and 'duration' in processed_dict['metropark']: message += f"metropark: {processed_dict['metropark']['duration']} |" return message |
7. Create a file named telegram_client.py, a script that handles messages sent on telegram, call different methods, collects the data from Zillow and Google, and sends a response back to the user.
telegram_client.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
import telepot # Importing the telepot library import config_util from telepot.loop import MessageLoop # Library function to communicate with telegram bot from time import sleep # Importing the time library to provide the delays in program from formatter import Formatter from google_client import GoogleClient from zillow_client import ZillowClient class TelegramClient: def __init__(self): self.bot = telepot.Bot(config_util.read_telegram_bot_token()) print(self.bot.getMe()) def start(self): MessageLoop(self.bot, self.handle).run_as_thread() print('Listening....') while 1: sleep(10) def handle(self, msg): # logger.info('handle: start', msg) chat_id = msg['chat']['id'] # Receiving the message from telegram url = msg['text'] # Getting text from the message new_dict = {'chat_id': chat_id, 'url': url} print(new_dict) self.process(new_dict) def process(self, request): try: processed_dict = self.get_home_details(request) address = self.get_address(processed_dict) new_dict = self.get_travel_distance(address) processed_dict.update(new_dict) if address: processed_dict['address'] = address print(processed_dict) formatter = Formatter() message = formatter.get_formatted_info(processed_dict) self.send_message(request['chat_id'], message) except Exception as e: self.send_message(request['chat_id'], "An error occurred") def send_message(self, chat_id, message): self.bot.sendMessage(chat_id, message) def get_home_details(self, request): processed_dict = {} if request and 'url' in request: zillow_client = ZillowClient() raw_dict = zillow_client.fetch(request['url']) processed_dict = zillow_client.process_fetched_content(raw_dict) return processed_dict def get_address(self, processed_dict): address = "" if processed_dict: address = f"{processed_dict['streetAddress']}, {processed_dict['city']}, {processed_dict['state']} {processed_dict['zipcode']} " return address def get_travel_distance(self, origin): google_client = GoogleClient() new_dict = google_client.get_travel_distance(origin) return new_dict if __name__ == '__main__': telegram_client = TelegramClient() telegram_client.start() |
Result
Conclusion
House hunting can be overwhelming, but integrating Zillow and Google Maps into our Telegram bot makes the process more efficient and user-friendly. By automating the retrieval of property data and providing distance information, our bot simplifies real estate research, allowing users to make informed decisions. Whether you’re a homebuyer, renter, or investor, our Telegram bot enhances your real estate experience and saves you precious time. Try it today and discover your dream property with ease!