Commit 3d179964 authored by Antoine BOSSY's avatar Antoine BOSSY Committed by hydrargyrum
Browse files

New CapHousing module: bienici

parent e98a0cdd
Pipeline #295311606 passed with stages
in 62 minutes and 53 seconds
# -*- coding: utf-8 -*-
# Copyright(C) 2018 Antoine BOSSY
#
# This file is part of woob.
#
# woob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# woob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with woob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from .module import BieniciModule
__all__ = ['BieniciModule']
# -*- coding: utf-8 -*-
# Copyright(C) 2018 Antoine BOSSY
#
# This file is part of woob.
#
# woob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# woob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with woob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from woob.browser import PagesBrowser, URL
from woob.tools.json import json
from woob.capabilities.housing import POSTS_TYPES, HOUSE_TYPES
from .pages import Cities, ResultsPage, HousingPage
TRANSACTION_TYPE = {
POSTS_TYPES.SALE: 'buy',
POSTS_TYPES.RENT: 'rent',
POSTS_TYPES.SALE: 'buy',
POSTS_TYPES.FURNISHED_RENT: 'rent',
POSTS_TYPES.SHARING: 'rent'
}
HOUSE_TYPES = {
HOUSE_TYPES.APART: ['flat'],
HOUSE_TYPES.HOUSE: ['house'],
HOUSE_TYPES.PARKING: ['parking'],
HOUSE_TYPES.LAND: ['terrain'],
HOUSE_TYPES.OTHER: ['others', 'loft', 'shop', 'building', 'castle', 'premises', 'office', 'townhouse'],
HOUSE_TYPES.UNKNOWN: []
}
class BieniciBrowser(PagesBrowser):
BASEURL = 'https://www.bienici.com'
cities = URL(r'https://res.bienici.com/suggest.json\?q=(?P<zipcode>.+)', Cities)
results = URL(r'/realEstateAds.json\?filters=(?P<filters>.+)', ResultsPage)
housing = URL(r'/realEstateAds-one.json\?filters=(?P<filters>.*)&onlyRealEstateAd=(?P<housing_id>.*)', HousingPage)
def get_cities(self, pattern):
return self.cities.go(zipcode=pattern).get_city()
def search_housing(self, query):
filters = {
'size': 100,
'page': 1,
'resultsPerPage': 24,
'maxAuthorizedResults': 2400,
'sortBy': "relevance",
'sortOrder': "desc",
'onTheMarket': [True],
'showAllModels': False,
"zoneIdsByTypes": {
'zoneIds': []
},
'propertyType': []
}
dict_query = query.to_dict()
if dict_query['area_min']:
filters['minArea'] = dict_query['area_min']
if dict_query['area_max']:
filters['maxArea'] = dict_query['area_max']
if dict_query['cost_min']:
filters['minPrice'] = dict_query['cost_min']
if dict_query['cost_max']:
filters['maxPrice'] = dict_query['cost_max']
filters['filterType'] = TRANSACTION_TYPE[dict_query['type']]
for housing_type in dict_query['house_types']:
filters['propertyType'] += HOUSE_TYPES[housing_type]
for city in dict_query['cities']:
filters['zoneIdsByTypes']['zoneIds'].append(city.id)
return self.results.go(filters=json.dumps(filters)).get_housings()
def get_housing(self, housing_id):
# This is to serialize correctly the JSON, and match the URL easier.
filters = {
'onTheMarket': [True]
}
return self.housing.go(housing_id=housing_id, filters=json.dumps(filters)).get_housing()
# -*- coding: utf-8 -*-
# Copyright(C) 2018 Antoine BOSSY
#
# This file is part of woob.
#
# woob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# woob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with woob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from woob.tools.backend import Module
from woob.capabilities.housing import CapHousing, Housing, HousingPhoto
from .browser import BieniciBrowser
__all__ = ['BieniciModule']
class BieniciModule(Module, CapHousing):
NAME = 'bienici'
DESCRIPTION = 'bienici website'
MAINTAINER = 'Antoine BOSSY'
EMAIL = 'mail+github@abossy.fr'
LICENSE = 'AGPLv3+'
VERSION = '3.1'
BROWSER = BieniciBrowser
def get_housing(self, id):
"""
Get an housing from an ID.
:param housing: ID of the housing
:type housing: str
:rtype: :class:`Housing` or None if not found.
"""
return self.browser.get_housing(id)
def search_city(self, pattern):
"""
Search a city from a pattern.
:param pattern: pattern to search
:type pattern: str
:rtype: iter[:class:`City`]
"""
return self.browser.get_cities(pattern)
def search_housings(self, query):
"""
Search housings.
:param query: search query
:type query: :class:`Query`
:rtype: iter[:class:`Housing`]
"""
return self.browser.search_housing(query)
def fill_photo(self, photo, fields):
"""
Fills the photo.
"""
if 'data' in fields and photo.url and not photo.data:
photo.data = self.browser.open(photo.url).content
return photo
def fill_housing(self, housing, fields):
"""
Fills the housing.
"""
return self.get_housing(housing.id)
OBJECTS = {HousingPhoto: fill_photo, Housing: fill_housing}
# -*- coding: utf-8 -*-
# Copyright(C) 2018 Antoine BOSSY
#
# This file is part of woob.
#
# woob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# woob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with woob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from woob.browser.pages import JsonPage
from woob.browser.elements import ItemElement, DictElement, method
from woob.browser.filters.json import Dict, ItemNotFound
from woob.capabilities.base import NotAvailable
from woob.browser.filters.standard import CleanText, Date, CleanDecimal
from woob.capabilities.housing import City, Housing, HousingPhoto, ENERGY_CLASS
class Cities(JsonPage):
@method
class get_city(DictElement):
class item(ItemElement):
klass = City
obj_id = Dict('zoneIds/0')
obj_name = CleanText(Dict('name'))
class MyItemElement(ItemElement):
klass = Housing
def condition(self):
return not Dict('userRelativeData/isAdModifier')(self)
obj_id = Dict('id')
obj_title = Dict('title')
obj_area = Dict('surfaceArea')
obj_cost = Dict('price')
def obj_price_per_meter(self):
try:
return Dict('pricePerSquareMeter')(self)
except ItemNotFound:
return NotAvailable
obj_currency = 'EUR'
obj_date = Date(Dict('publicationDate'))
obj_location = CleanDecimal(Dict('postalCode'))
obj_text = Dict('description', '')
def obj_photos(self):
return [HousingPhoto(photo['url']) for photo in Dict('photos')(self)]
obj_rooms = Dict('roomsQuantity', 0)
obj_bedrooms = Dict('bedroomsQuantity', 0)
def obj_DPE(self):
try:
return ENERGY_CLASS[Dict('energyClassification')(self)]
except (KeyError, ItemNotFound):
return NotAvailable
def obj_GES(self):
try:
return ENERGY_CLASS[Dict('greenhouseGazClassification')(self)]
except (KeyError, ItemNotFound):
return NotAvailable
class ResultsPage(JsonPage):
@method
class get_housings(DictElement):
item_xpath = 'realEstateAds'
class item(MyItemElement):
pass
class HousingPage(JsonPage):
@method
class get_housing(MyItemElement):
pass
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment