Skip to main content

A centralized method of accessing appraiser data, using each counties local property appraiser's data.

Project description

CentralizedAppraiser

A new form of accessing real estate data because nobody wants to pay >$80,000 for Regrid and still not have access to up to date information.

TRY IT WITH ANY ADDRESS IN MIAMIDADE/BROWARD COUNTY.

Installation

pip install CentralizedAppraiser

This may be used in unison with regrid, however, it is distinguished in a few ways:

  • It dynamically accesses property appraiser data (meaning it is always up to date)
  • It enables you to access all the additional county specific data
  • It enables you to interact with the county website (for example, to screenshot the property appraiser website)
  • It is free
  • It is open source (please contribute)

Below are the steps explaining how this library works:

  1. Create a client of a map provider (for example, google maps, regrid, apple maps, etc.)
  2. Geocode the address and get the address components (no matter what client you use CentralizedAppraiser will ensure the address components are standardized)
  3. Determine the county which the address is in
  4. Determine the folio if not provided
  5. Request the data from the county (this is similarly standardized so that all municipalities/cities can be accessed in the same way)

Usage Examples

Using the Google Maps client, get the appraiser info for an address given the Google Place ID. Also refer to the examples directory for more examples in the github repository.

Regrid Client

This is a simple implementation which when given an address, it will return the appraiser information.

import CentralizedAppraiser
from CentralizedAppraiser.clients import RegridClient

client = RegridClient("YOUR_REGRID_API_KEY")
addressInfo, errorHandler = client.getByAddress("6760 SW 48TH ST")
appraiserInfo, errorHandler = CentralizedAppraiser.appraiserInfoByAddressInfo(addressInfo, client)

print(appraiserInfo.get())

This is a more complex implementation which accomplishes the same thing as the above code, however it is more verbose and shows each step of the process.

import CentralizedAppraiser
from CentralizedAppraiser.clients import RegridClient

client = RegridClient("YOUR_REGRID_API_KEY") # API KEY
addressInfo, errorHandler = client.getByAddress("6760 SW 48TH ST")
classPointer, errorHandler = CentralizedAppraiser.classByAddressInfo(addressInfo)
data, errorHandler = addressInfo.get()
# folio, errorHandler = classPointer.folioByAddressInfo(addressInfo) # commented out because Regrid already provides the folio
appraiserInfo, errorHandler = classPointer.appraiserInfoByFolio(data["folio"], client)

print(appraiserInfo.get())

Google Client

This is a simple implementation which when given an address, it will return the appraiser information.

import CentralizedAppraiser
from CentralizedAppraiser.clients import GoogleClient

client = GoogleClient("YOUR_GOOGLE_API_KEY")
addressInfo, errorHandler = client.getByAddress("6760 SW 48TH ST")
appraiserInfo, errorHandler = CentralizedAppraiser.appraiserInfoByAddressInfo(addressInfo, client)

print(appraiserInfo.get())

This is a more complex implementation which accomplishes the same thing as the above code, however it is more verbose and shows each step of the process.

import CentralizedAppraiser
from CentralizedAppraiser.clients import GoogleClient

client = GoogleClient("YOUR_GOOGLE_API_KEY") # API KEY
addressInfo, errorHandler = client.getByAddress("6760 SW 48TH ST")
classPointer, errorHandler = CentralizedAppraiser.classByAddressInfo(addressInfo)
folio, errorHandler = classPointer.folioByAddressInfo(addressInfo)
appraiserInfo, errorHandler = classPointer.appraiserInfoByFolio(folio, client)

print(appraiserInfo.get())

Functions

CentralizedAppraiser

  • appraiserInfoByAddressInfo(addressInfo:AddressInfo, client:Client) -> set[AppraiserInfo, dict]
    • Returns the appraiser info by the address info
  • classByAddressInfo(addressInfo:AddressInfo) -> set[Country, dict]
    • Returns the class pointer by the address info
  • classByPath(path:list) -> set[Country, dict]
    • Returns the class pointer by the path to the county website
  • pathByAddressInfo(addressInfo:AddressInfo) -> set[list, dict]
    • Returns the path to the county website as a list of strings

AddressSchematic (extended by AddressInfo, and AppraiserInfo)

  • __init__(self, data:dict, client, translateStrategy) -> None
    • Initializes the AddressSchematic object
  • get(self) -> set[dict, dict]
    • Returns the standardized address components and the error handler

Client (extended by GoogleClient, and RegridClient)

  • __init__(self, key:str="") -> None
    • Initializes the client object with an api key
  • getByAddress(self, location:str) -> set[AddressInfo, dict]
    • Returns the address info by the location as a string
  • getByID(self, placeID:str) -> set[AddressInfo, dict]
    • Returns the address info by the place id as a string
  • __translate(cls, data: dict) -> dict
    • Translates the data to the standardized format from the client's format

Country (*extended by all other locations)

  • def getDefiningGeometryKey(cls) -> str:
    • Returns the key for the geometry json parameters
  • def folioByAddressInfo(cls, search:AddressInfo) -> set[str, dict]:
    • Returns the folio by the address info
  • def appraiserInfoByFolio(cls, folio:str, client:Client) -> set[AppraiserInfo, dict]:
    • Returns the appraiser info by the folio
  • def appraiserInfoByAddressInfo(cls, search:AddressInfo, client:Client) -> set[AppraiserInfo, dict]:
    • Returns the appraiser info by the address info. This just implements the folioByAddressInfo and appraiserInfoByFolio functions
  • def getScreenshotByFolio(cls, folio:str) -> set[bool, dict]:
    • Returns the screenshot of the property appraiser website by the folio with selenium

Schemas

The following are various schemas used by different parts of the program. These schemas are used to ensure that the data is standardized and that the data is correct. The schemas are written with the schema library.

AddressInfo Schema

Schema({
    "formattedAddress": And(str, len),
    "folio": Or(None, And(str, Use(len))),
    "addressComponents": {
        "streetNumber": str,
        "street": str,
        "streetDirection": str,
        "city": str,
        "county": str,
        "state": And(str, len),
        "country": And(str, len),
        "zip": And(str, len)
    },
    "geo": {
        "lat": And(Use(float), lambda n: -90 <= n <= 90),
        "lng": And(Use(float), lambda n: -180 <= n <= 180)
    }
})

AppraiserInfo Schema

Schema({
    "assessments": [
        {
            "assessedValue": And(int, lambda n: n >= 0),
            
            "buildingValue": And(int, lambda n: n >= 0),
            "landValue": And(int, lambda n: n >= 0),
            "totalValue": And(int, lambda n: n >= 0),
            "year": int
        },
    ],
    "propertyInfo": {
        "folio": And(str, len),
        "parentFolio": str,
        "legal": str,
        "use": int,
        "subdivision": str,
        "blk": int,
        "lot": int,
        "plat": {
            "book": int,
            "page": int
        },
        "lotSize": Or(None, int, float),
        "otherRecords": [
            {
                "type": str,
                "book": int,
                "page": int
            }
        ]
    },
    "owners": [
        {
            "name": And(str, len),
            # "type": str, Should be used for sole proprietorship, partnership, LLC, etc
            "mailingAddresses": [
                {
                    "formattedAddress": And(str, len),
                    'folio': Or(None, And(str, Use(len))),
                    "addressComponents": {
                        "streetNumber": str,
                        "street": str,
                        "streetDirection": str,
                        "city": str,
                        "county": str,
                        "state": And(str, len),
                        "country": And(str, len),
                        "zip": And(str, len)
                    },
                    "geo": {
                        "lat": And(Use(float), lambda n: -90 <= n <= 90),
                        "lng": And(Use(float), lambda n: -180 <= n <= 180)
                    }
                }
            ]
        }
    ],
    Optional("unStructured"): dict
})

Error Schema

Schema({
    "status": Or("error", "success"), # "error" or "success"
    "message": str,
})

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

centralizedappraiser-0.0.9.tar.gz (21.7 MB view details)

Uploaded Source

Built Distribution

CentralizedAppraiser-0.0.9-py3-none-any.whl (21.8 MB view details)

Uploaded Python 3

File details

Details for the file centralizedappraiser-0.0.9.tar.gz.

File metadata

  • Download URL: centralizedappraiser-0.0.9.tar.gz
  • Upload date:
  • Size: 21.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.5

File hashes

Hashes for centralizedappraiser-0.0.9.tar.gz
Algorithm Hash digest
SHA256 f10a74c1da0a888557e0eca9bbcc3af9815282eee9c693e979030521008b6036
MD5 b41145baa5f352c4462cf0ee968b9c0c
BLAKE2b-256 25d85ee5c597dc3f0fda5e1e56f8eabd38134c41b2817b62996995f670545948

See more details on using hashes here.

File details

Details for the file CentralizedAppraiser-0.0.9-py3-none-any.whl.

File metadata

File hashes

Hashes for CentralizedAppraiser-0.0.9-py3-none-any.whl
Algorithm Hash digest
SHA256 7e297c5c458310e6f431d3ae16589fdc48e168c8b03624ae7443216cb5543fb3
MD5 dc4c071be5182c493f9a5eebf336080f
BLAKE2b-256 72684883360f3fbcd02ca3d23253bbd65955e6f011dd6f826cc73e7eb3dd4568

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page