Commit 2ce519dc authored by Antoine BOSSY's avatar Antoine BOSSY

New CapHousing module: bienici

parent f813a626
Pipeline #1767 failed with stages
in 0 seconds
# -*- coding: utf-8 -*-
# Copyright(C) 2018 Antoine BOSSY
#
# This file is part of weboob.
#
# weboob 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.
#
# weboob 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 weboob. 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 weboob.
#
# weboob 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.
#
# weboob 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 weboob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from weboob.browser import PagesBrowser, URL
from weboob.tools.json import json
from weboob.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 weboob.
#
# weboob 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.
#
# weboob 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 weboob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from weboob.tools.backend import Module
from weboob.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 = '1.4'
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 weboob.
#
# weboob 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.
#
# weboob 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 weboob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from weboob.browser.pages import JsonPage
from weboob.browser.elements import ItemElement, DictElement, method
from weboob.browser.filters.json import Dict, ItemNotFound
from weboob.capabilities.base import NotAvailable
from weboob.browser.filters.standard import CleanText, Date, CleanDecimal
from weboob.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
# -*- coding: utf-8 -*-
# Copyright(C) 2018 Antoine BOSSY
#
# This file is part of weboob.
#
# weboob 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.
#
# weboob 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 weboob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from weboob.tools.test import BackendTest
class BieniciTest(BackendTest):
MODULE = 'bienici'
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