Skip to content

Commit 9536c3c

Browse files
committed
init
0 parents  commit 9536c3c

File tree

9 files changed

+262
-0
lines changed

9 files changed

+262
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__pycache__/

LICENSE.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
MIT License
2+
Copyright (c) 2018 YOUR NAME
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
The above copyright notice and this permission notice shall be included in all
10+
copies or substantial portions of the Software.
11+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17+
SOFTWARE.

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Python-Redfin
2+
3+
### Installation
4+
5+
```
6+
$ python3 -m pip install python-redfin
7+
```
8+
9+
### Usage
10+
11+
```python3
12+
13+
from redfin import Redfin
14+
15+
client = Redfin()
16+
17+
address = '4544 Radnor St, Detroit Michigan'
18+
19+
response = client.search(ADDRESS)
20+
url = response['payload']['exactMatch']['url']
21+
initial_info = engine.initial_info(url)
22+
23+
property_id = data['payload']['propertyId']
24+
listing_id = data['payload']['listingId']
25+
26+
mls_data = client.below_the_fold(property_id, listing_id)
27+
```

python-redfin/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from redfin.redfin import Redfin

python-redfin/redfin.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import requests
2+
import json
3+
4+
class Redfin:
5+
def __init__(self):
6+
self.base = 'https://redfin.com/stingray/'
7+
self.user_agent_header = {
8+
'user-agent': 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Safari/537.36'
9+
}
10+
11+
def meta_property(self, url, kwargs, page=False):
12+
if page:
13+
kwargs['pageType'] = 3
14+
return self.meta_request('api/home/details/' + url, {
15+
'accessLevel': 1,
16+
**kwargs
17+
})
18+
19+
def meta_request(self, url, kwargs):
20+
response = requests.get(self.base + url, params=kwargs, headers=self.user_agent_header)
21+
response.raise_for_status()
22+
return json.loads(response.text[4:])
23+
24+
# Url Requests
25+
26+
def initial_info(self, url, **kwargs):
27+
return self.meta_request('api/home/details/initialInfo', {'path': url,**kwargs})
28+
29+
def page_tags(self, url, **kwargs):
30+
return self.meta_request('api/home/details/v1/pagetagsinfo', {'path': url, **kwargs})
31+
32+
def primary_region(self, url, **kwargs):
33+
return self.meta_request('api/home/details/primaryRegionInfo', {'path': url, **kwargs})
34+
35+
# Search
36+
def search(self, query, **kwargs):
37+
return self.meta_request('do/location-autocomplete', {'location': query, 'v': 2, **kwargs})
38+
39+
# Property ID Requests
40+
def hood_photos(self, property_id, **kwargs):
41+
return self.meta_request('api/home/details/hood-photos', {'propertyId': property_id, **kwargs})
42+
43+
def more_resources(self, property_id, **kwargs):
44+
return self.meta_request('api/home/details/moreResourcesInfo', {'propertyId': property_id, **kwargs})
45+
46+
def page_header(self, property_id, **kwargs):
47+
return self.meta_request('api/home/details/homeDetailsPageHeaderInfo', {'propertyId': property_id, **kwargs})
48+
49+
def property_comments(self, property_id, **kwargs):
50+
return self.meta_request('api/v1/home/details/propertyCommentsInfo', {'propertyId': property_id, **kwargs})
51+
52+
def building_details_page(self, property_id, **kwargs):
53+
return self.meta_request('api/building/details-page/v1', {'propertyId': property_id, **kwargs})
54+
55+
def owner_estimate(self, property_id, **kwargs):
56+
return self.meta_request('api/home/details/owner-estimate', {'propertyId': property_id, **kwargs})
57+
58+
def claimed_home_seller_data(self, property_id, **kwargs):
59+
return self.meta_request('api/home/details/claimedHomeSellerData', {'propertyId': property_id, **kwargs})
60+
61+
def cost_of_home_ownership(self, property_id, **kwargs):
62+
return self.meta_request('do/api/costOfHomeOwnershipDetails', {'propertyId': property_id, **kwargs})
63+
64+
# Listing ID Requests
65+
def floor_plans(self, listing_id, **kwargs):
66+
return self.meta_request('api/home/details/listing/floorplans', {'listingId': listing_id, **kwargs})
67+
68+
def tour_list_date_picker(self, listing_id, **kwargs):
69+
return self.meta_request('do/tourlist/getDatePickerData', {'listingId': listing_id, **kwargs})
70+
71+
# Table ID Requests
72+
73+
def shared_region(self, table_id, **kwargs):
74+
return self.meta_request('api/region/shared-region-info', {'tableId': table_id, 'regionTypeId': 2, 'mapPageTypeId': 1, **kwargs})
75+
76+
# Property Requests
77+
78+
def similar_listings(self, property_id, listing_id, **kwargs):
79+
return self.meta_property('similars/listings', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
80+
81+
def similar_sold(self, property_id, listing_id, **kwargs):
82+
return self.meta_property('similars/solds', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
83+
84+
def nearby_homes(self, property_id, listing_id, **kwargs):
85+
return self.meta_property('nearbyhomes', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
86+
87+
def above_the_fold(self, property_id, listing_id, **kwargs):
88+
return self.meta_property('aboveTheFold', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
89+
90+
def below_the_fold(self, property_id, listing_id, **kwargs):
91+
return self.meta_property('belowTheFold', {'propertyId': property_id, 'listingId': listing_id, **kwargs}, page=True)
92+
93+
def property_parcel(self, property_id, listing_id, **kwargs):
94+
return self.meta_property('propertyParcelInfo', {'propertyId': property_id, 'listingId': listing_id, **kwargs}, page=True)
95+
96+
def activity(self, property_id, listing_id, **kwargs):
97+
return self.meta_property('activityInfo', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
98+
99+
def customer_conversion_info_off_market(self, property_id, listing_id, **kwargs):
100+
return self.meta_property('customerConversionInfo/offMarket', {'propertyId': property_id, 'listingId': listing_id, **kwargs}, page=True)
101+
102+
def rental_estimate(self, property_id, listing_id, **kwargs):
103+
return self.meta_property('rental-estimate', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
104+
105+
def avm_historical(self, property_id, listing_id, **kwargs):
106+
return self.meta_property('avmHistoricalData', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
107+
108+
def info_panel(self, property_id, listing_id, **kwargs):
109+
return self.meta_property('mainHouseInfoPanelInfo', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
110+
111+
def descriptive_paragraph(self, property_id, listing_id, **kwargs):
112+
return self.meta_property('descriptiveParagraph', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
113+
114+
def avm_details(self, property_id, listing_id, **kwargs):
115+
return self.meta_property('avm', {'propertyId': property_id, 'listingId': listing_id, **kwargs})
116+
117+
def tour_insights(self, property_id, listing_id, **kwargs):
118+
return self.meta_property('tourInsights', {'propertyId': property_id, 'listingId': listing_id, **kwargs}, page=True)
119+
120+
def stats(self, property_id, listing_id, region_id, **kwargs):
121+
return self.meta_property('stats', {'regionId': region_id, 'propertyId': property_id, 'listingId': listing_id, 'regionTypeId': 2, **kwargs})

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
requests

setup.cfg

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
# Inside of setup.cfg
3+
[metadata]
4+
description-file = README.md

setup.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from distutils.core import setup
2+
setup(
3+
name = 'python-redfin', # How you named your package folder (MyLib)
4+
packages = ['python-redfin'], # Chose the same as "name"
5+
version = '0.1', # Start with a small number and increase it with every change you make
6+
license='MIT', # Chose a license from here: https://help.github.com/articles/licensing-a-repository
7+
description = 'A python wrapper around the unofficial redfin API.', # Give a short description about your library
8+
author = 'Peter Stenger', # Type in your name
9+
author_email = 'peter.promotions.stenger@gmail.com', # Type in your E-Mail
10+
url = 'https://github.com/reteps/python-redfin', # Provide either the link to your github or to your website
11+
download_url = 'https://github.com/user/reponame/archive/v_01.tar.gz', # I explain this later on
12+
keywords = ['redfin', 'api', 'wrapper'], # Keywords that define your package best
13+
install_requires=[ # I get to this in a second
14+
'requests'
15+
],
16+
classifiers=[
17+
'Development Status :: 3 - Alpha', # Chose either "3 - Alpha", "4 - Beta" or "5 - Production/Stable" as the current state of your package
18+
'Intended Audience :: Developers', # Define that your audience are developers
19+
'Topic :: Software Development :: Build Tools',
20+
'License :: OSI Approved :: MIT License', # Again, pick a license
21+
'Programming Language :: Python :: 3', #Specify which pyhton versions that you want to support
22+
'Programming Language :: Python :: 3.4',
23+
'Programming Language :: Python :: 3.5',
24+
'Programming Language :: Python :: 3.6',
25+
],
26+
)

test.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
from redfin import Redfin
2+
import json
3+
ADDRESS = '4544 Radnor St, Detroit Michigan'
4+
5+
engine = Redfin()
6+
7+
response = engine.search(ADDRESS)
8+
9+
url = response['payload']['exactMatch']['url']
10+
data = engine.initial_info(url)['payload']
11+
property_id = data['propertyId']
12+
listing_id = data['listingId']
13+
14+
URL_REQUESTS = [
15+
engine.page_tags,
16+
engine.primary_region
17+
]
18+
PROPERTY_ID_REQUESTS = [
19+
engine.hood_photos,
20+
engine.more_resources,
21+
engine.page_header,
22+
engine.property_comments,
23+
engine.building_details_page,
24+
engine.owner_estimate,
25+
engine.claimed_home_seller_data,
26+
engine.cost_of_home_ownership
27+
]
28+
LISTING_ID_REQUESTS = [
29+
engine.floor_plans,
30+
engine.tour_list_date_picker
31+
]
32+
PROPERTY_REQUESTS = [
33+
engine.similar_listings,
34+
engine.similar_sold,
35+
engine.nearby_homes,
36+
engine.above_the_fold,
37+
engine.below_the_fold,
38+
engine.property_parcel,
39+
engine.activity,
40+
engine.customer_conversion_info_off_market,
41+
engine.rental_estimate,
42+
engine.avm_historical,
43+
engine.info_panel,
44+
engine.descriptive_paragraph,
45+
engine.avm_details,
46+
engine.tour_insights,
47+
]
48+
49+
# TODO test these resources
50+
OTHER_REQUESTS = [
51+
engine.stats,
52+
engine.shared_region
53+
]
54+
55+
def test_request_group(fns, *args):
56+
for fn in fns:
57+
fn(*args)
58+
59+
test_request_group(URL_REQUESTS, url)
60+
test_request_group(PROPERTY_ID_REQUESTS, property_id)
61+
test_request_group(LISTING_ID_REQUESTS, listing_id)
62+
test_request_group(PROPERTY_REQUESTS, property_id, listing_id)
63+
64+
print('Tests passed.')

0 commit comments

Comments
 (0)