can looking for a rent or a sale
This commit is contained in:
parent
3eddf8e6dd
commit
f5ca33f80e
9 changed files with 79 additions and 29 deletions
|
|
@ -41,7 +41,7 @@ class PapBackend(BaseBackend, ICapHousing):
|
||||||
return list()
|
return list()
|
||||||
|
|
||||||
with self.browser:
|
with self.browser:
|
||||||
return self.browser.search_housings(cities, query.nb_rooms,
|
return self.browser.search_housings(query.type, cities, query.nb_rooms,
|
||||||
query.area_min, query.area_max,
|
query.area_min, query.area_max,
|
||||||
query.cost_min, query.cost_max)
|
query.cost_min, query.cost_max)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import urllib
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from weboob.tools.browser import BaseBrowser
|
from weboob.tools.browser import BaseBrowser
|
||||||
|
from weboob.capabilities.housing import Query
|
||||||
|
|
||||||
from .pages import SearchResultsPage, HousingPage
|
from .pages import SearchResultsPage, HousingPage
|
||||||
|
|
||||||
|
|
@ -42,13 +43,16 @@ class PapBrowser(BaseBrowser):
|
||||||
fp = self.openurl(self.buildurl('http://www.pap.fr/index/ac-geo', q=pattern))
|
fp = self.openurl(self.buildurl('http://www.pap.fr/index/ac-geo', q=pattern))
|
||||||
return json.load(fp)
|
return json.load(fp)
|
||||||
|
|
||||||
def search_housings(self, cities, nb_rooms, area_min, area_max, cost_min, cost_max):
|
TYPES = {Query.TYPE_RENT: 'location',
|
||||||
|
Query.TYPE_SALE: 'vente',
|
||||||
|
}
|
||||||
|
def search_housings(self, type, cities, nb_rooms, area_min, area_max, cost_min, cost_max):
|
||||||
data = {'geo_objets_ids': ','.join(cities),
|
data = {'geo_objets_ids': ','.join(cities),
|
||||||
'surface[min]': area_min or '',
|
'surface[min]': area_min or '',
|
||||||
'surface[max]': area_max or '',
|
'surface[max]': area_max or '',
|
||||||
'prix[min]': cost_min or '',
|
'prix[min]': cost_min or '',
|
||||||
'prix[max]': cost_max or '',
|
'prix[max]': cost_max or '',
|
||||||
'produit': 'location',
|
'produit': self.TYPES.get(type, 'location'),
|
||||||
'recherche': 1,
|
'recherche': 1,
|
||||||
'nb_resultats_par_page': 40,
|
'nb_resultats_par_page': 40,
|
||||||
'submit': 'rechercher',
|
'submit': 'rechercher',
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,11 @@ class SearchResultsPage(BasePage):
|
||||||
id = a.attrib['href'].split('-')[-1]
|
id = a.attrib['href'].split('-')[-1]
|
||||||
housing = Housing(id)
|
housing = Housing(id)
|
||||||
housing.title = a.text.strip()
|
housing.title = a.text.strip()
|
||||||
housing.cost = int(div.cssselect('td.prix')[0].text.strip(u' \t\u20ac\xa0€\n\r'))
|
m = re.match('(\w+) (.+) (\d+)\xa0m\xb2 (.*)', housing.title)
|
||||||
|
if m:
|
||||||
|
housing.area = float(m.group(3))
|
||||||
|
|
||||||
|
housing.cost = float(div.cssselect('td.prix')[0].text.strip(u' \t\u20ac\xa0€\n\r').replace('.', '').replace(',', '.'))
|
||||||
housing.currency = u'€'
|
housing.currency = u'€'
|
||||||
|
|
||||||
m = self.DATE_RE.match(div.cssselect('p.date-publication')[0].text.strip())
|
m = self.DATE_RE.match(div.cssselect('p.date-publication')[0].text.strip())
|
||||||
|
|
@ -75,6 +79,8 @@ class SearchResultsPage(BasePage):
|
||||||
else:
|
else:
|
||||||
housing.text = p.text.strip()
|
housing.text = p.text.strip()
|
||||||
|
|
||||||
|
housing.photos = NotAvailable
|
||||||
|
|
||||||
yield housing
|
yield housing
|
||||||
|
|
||||||
class HousingPage(BasePage):
|
class HousingPage(BasePage):
|
||||||
|
|
@ -84,12 +90,12 @@ class HousingPage(BasePage):
|
||||||
|
|
||||||
parts = div.find('h1').text.split(' - ')
|
parts = div.find('h1').text.split(' - ')
|
||||||
housing.title = parts[0].strip()
|
housing.title = parts[0].strip()
|
||||||
housing.cost = int(parts[1].strip(u' \t\u20ac\xa0€\n\r'))
|
housing.cost = float(parts[1].strip(u' \t\u20ac\xa0€\n\r').replace('.', '').replace(',', '.'))
|
||||||
housing.currency = u'€'
|
housing.currency = u'€'
|
||||||
|
|
||||||
m = re.match('(\w+) ([\w\s]+) (\d+)\xa0m\xb2 (.*)', housing.title)
|
m = re.match('(\w+) (.+) (\d+)\xa0m\xb2 (.*)', housing.title)
|
||||||
if m:
|
if m:
|
||||||
housing.area = int(m.group(3))
|
housing.area = float(m.group(3))
|
||||||
|
|
||||||
housing.date = housing.station = housing.location = housing.phone = NotAvailable
|
housing.date = housing.station = housing.location = housing.phone = NotAvailable
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class SeLogerBackend(BaseBackend, ICapHousing):
|
||||||
return list([])
|
return list([])
|
||||||
|
|
||||||
with self.browser:
|
with self.browser:
|
||||||
return self.browser.search_housings(cities, query.nb_rooms,
|
return self.browser.search_housings(query.type, cities, query.nb_rooms,
|
||||||
query.area_min, query.area_max,
|
query.area_min, query.area_max,
|
||||||
query.cost_min, query.cost_max)
|
query.cost_min, query.cost_max)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from weboob.tools.browser import BaseBrowser
|
from weboob.tools.browser import BaseBrowser
|
||||||
|
from weboob.capabilities.housing import Query
|
||||||
|
|
||||||
from .pages import SearchResultsPage, HousingPage
|
from .pages import SearchResultsPage, HousingPage
|
||||||
|
|
||||||
|
|
@ -42,18 +43,27 @@ class SeLogerBrowser(BaseBrowser):
|
||||||
fp = self.openurl(self.buildurl('http://www.seloger.com/js,ajax,villequery_v3.htm', ville=pattern, mode=1))
|
fp = self.openurl(self.buildurl('http://www.seloger.com/js,ajax,villequery_v3.htm', ville=pattern, mode=1))
|
||||||
return json.load(fp)
|
return json.load(fp)
|
||||||
|
|
||||||
def search_housings(self, cities, nb_rooms, area_min, area_max, cost_min, cost_max):
|
TYPES = {Query.TYPE_RENT: 1,
|
||||||
|
Query.TYPE_SALE: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
def search_housings(self, type, cities, nb_rooms, area_min, area_max, cost_min, cost_max):
|
||||||
data = {'ci': ','.join(cities),
|
data = {'ci': ','.join(cities),
|
||||||
'idtt': 1, #location
|
'idtt': self.TYPES.get(type, 1),
|
||||||
'idtypebien': 1, #appart
|
'idtypebien': 1, #appart
|
||||||
'org': 'advanced_search',
|
'org': 'advanced_search',
|
||||||
'px_loyermax': cost_max or '',
|
|
||||||
'px_loyermin': cost_min or '',
|
|
||||||
'surfacemax': area_max or '',
|
'surfacemax': area_max or '',
|
||||||
'surfacemin': area_min or '',
|
'surfacemin': area_min or '',
|
||||||
'tri': 'd_dt_crea',
|
'tri': 'd_dt_crea',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if type == Query.TYPE_SALE:
|
||||||
|
data['pxmax'] = cost_max or ''
|
||||||
|
data['pxmin'] = cost_min or ''
|
||||||
|
else:
|
||||||
|
data['px_loyermax'] = cost_max or ''
|
||||||
|
data['px_loyermin'] = cost_min or ''
|
||||||
|
|
||||||
if nb_rooms:
|
if nb_rooms:
|
||||||
data['nb_pieces'] = nb_rooms
|
data['nb_pieces'] = nb_rooms
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ from PyQt4.QtCore import SIGNAL, Qt
|
||||||
from weboob.tools.application.qt import QtMainWindow, QtDo, HTMLDelegate
|
from weboob.tools.application.qt import QtMainWindow, QtDo, HTMLDelegate
|
||||||
from weboob.tools.application.qt.backendcfg import BackendCfg
|
from weboob.tools.application.qt.backendcfg import BackendCfg
|
||||||
from weboob.capabilities.housing import ICapHousing, Query, City
|
from weboob.capabilities.housing import ICapHousing, Query, City
|
||||||
from weboob.capabilities.base import NotLoaded
|
from weboob.capabilities.base import NotLoaded, NotAvailable
|
||||||
|
|
||||||
from .ui.main_window_ui import Ui_MainWindow
|
from .ui.main_window_ui import Ui_MainWindow
|
||||||
from .query import QueryDialog
|
from .query import QueryDialog
|
||||||
|
|
@ -35,8 +35,8 @@ class HousingListWidgetItem(QListWidgetItem):
|
||||||
self.read = False
|
self.read = False
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
return '%s%s' % (self.read, float(self.housing.cost) / float(self.housing.area)) < \
|
return '%s%s' % (self.read, float(self.housing.cost or 0) / float(self.housing.area or 1)) < \
|
||||||
'%s%s' % (other.read, float(other.housing.cost) / float(other.housing.area))
|
'%s%s' % (other.read, float(other.housing.cost or 0) / float(other.housing.area or 1))
|
||||||
|
|
||||||
def setAttrs(self, storage):
|
def setAttrs(self, storage):
|
||||||
text = u'<h2>%s</h2>' % self.housing.title
|
text = u'<h2>%s</h2>' % self.housing.title
|
||||||
|
|
@ -53,6 +53,8 @@ class HousingListWidgetItem(QListWidgetItem):
|
||||||
self.read = True
|
self.read = True
|
||||||
if self.housing.fullid in storage.get('bookmarks'):
|
if self.housing.fullid in storage.get('bookmarks'):
|
||||||
self.setBackground(QBrush(QColor(255, 200, 200)))
|
self.setBackground(QBrush(QColor(255, 200, 200)))
|
||||||
|
elif self.background().color() != QColor(0,0,0):
|
||||||
|
self.setBackground(QBrush())
|
||||||
|
|
||||||
class MainWindow(QtMainWindow):
|
class MainWindow(QtMainWindow):
|
||||||
def __init__(self, config, storage, weboob, parent=None):
|
def __init__(self, config, storage, weboob, parent=None):
|
||||||
|
|
@ -140,18 +142,17 @@ class MainWindow(QtMainWindow):
|
||||||
item = querydlg.buildCityItem(city)
|
item = querydlg.buildCityItem(city)
|
||||||
querydlg.ui.citiesList.addItem(item)
|
querydlg.ui.citiesList.addItem(item)
|
||||||
|
|
||||||
|
querydlg.ui.typeBox.setCurrentIndex(int(query.get('type', 0)))
|
||||||
querydlg.ui.areaMin.setValue(query['area_min'])
|
querydlg.ui.areaMin.setValue(query['area_min'])
|
||||||
querydlg.ui.areaMax.setValue(query['area_max'])
|
querydlg.ui.areaMax.setValue(query['area_max'])
|
||||||
querydlg.ui.costMin.setValue(query['cost_min'])
|
querydlg.ui.costMin.setValue(query['cost_min'])
|
||||||
querydlg.ui.costMax.setValue(query['cost_max'])
|
querydlg.ui.costMax.setValue(query['cost_max'])
|
||||||
for i in xrange(querydlg.ui.nbRooms.count()):
|
querydlg.selectComboValue(querydlg.ui.nbRooms, query['nb_rooms'])
|
||||||
if querydlg.ui.nbRooms.itemText(i) == str(query['nb_rooms']):
|
|
||||||
querydlg.ui.nbRooms.setCurrentIndex(i)
|
|
||||||
break
|
|
||||||
|
|
||||||
if querydlg.exec_():
|
if querydlg.exec_():
|
||||||
name = unicode(querydlg.ui.nameEdit.text())
|
name = unicode(querydlg.ui.nameEdit.text())
|
||||||
query = {}
|
query = {}
|
||||||
|
query['type'] = querydlg.ui.typeBox.currentIndex()
|
||||||
query['cities'] = []
|
query['cities'] = []
|
||||||
for i in xrange(len(querydlg.ui.citiesList)):
|
for i in xrange(len(querydlg.ui.citiesList)):
|
||||||
item = querydlg.ui.citiesList.item(i)
|
item = querydlg.ui.citiesList.item(i)
|
||||||
|
|
@ -185,6 +186,7 @@ class MainWindow(QtMainWindow):
|
||||||
self.ui.bookmarksButton.setEnabled(False)
|
self.ui.bookmarksButton.setEnabled(False)
|
||||||
|
|
||||||
query = Query()
|
query = Query()
|
||||||
|
query.type = int(q.get('type', 0))
|
||||||
query.cities = []
|
query.cities = []
|
||||||
for c in q['cities']:
|
for c in q['cities']:
|
||||||
city = City(c['id'])
|
city = City(c['id'])
|
||||||
|
|
@ -227,7 +229,7 @@ class MainWindow(QtMainWindow):
|
||||||
process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
|
process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
|
||||||
process.do('fillobj', housing, ['photos'], backends=housing.backend)
|
process.do('fillobj', housing, ['photos'], backends=housing.backend)
|
||||||
self.process_photo[housing.id] = process
|
self.process_photo[housing.id] = process
|
||||||
elif len(housing.photos) > 0:
|
elif housing.photos is not NotAvailable and len(housing.photos) > 0:
|
||||||
if not self.setPhoto(housing, item):
|
if not self.setPhoto(housing, item):
|
||||||
photo = housing.photos[0]
|
photo = housing.photos[0]
|
||||||
process = QtDo(self.weboob, lambda b, p: self.setPhoto(housing, item))
|
process = QtDo(self.weboob, lambda b, p: self.setPhoto(housing, item))
|
||||||
|
|
@ -240,22 +242,26 @@ class MainWindow(QtMainWindow):
|
||||||
self.process_bookmarks.pop(housing.fullid)
|
self.process_bookmarks.pop(housing.fullid)
|
||||||
|
|
||||||
def housingSelected(self, item, prev):
|
def housingSelected(self, item, prev):
|
||||||
housing = item.housing
|
if item is not None:
|
||||||
self.ui.queriesFrame.setEnabled(False)
|
housing = item.housing
|
||||||
|
self.ui.queriesFrame.setEnabled(False)
|
||||||
|
|
||||||
read = set(self.storage.get('read'))
|
read = set(self.storage.get('read'))
|
||||||
read.add(housing.fullid)
|
read.add(housing.fullid)
|
||||||
self.storage.set('read', list(read))
|
self.storage.set('read', list(read))
|
||||||
self.storage.save()
|
self.storage.save()
|
||||||
|
|
||||||
|
self.process = QtDo(self.weboob, self.gotHousing)
|
||||||
|
self.process.do('fillobj', housing, backends=housing.backend)
|
||||||
|
|
||||||
|
else:
|
||||||
|
housing = None
|
||||||
|
|
||||||
self.setHousing(housing)
|
self.setHousing(housing)
|
||||||
|
|
||||||
if prev:
|
if prev:
|
||||||
prev.setAttrs(self.storage)
|
prev.setAttrs(self.storage)
|
||||||
|
|
||||||
self.process = QtDo(self.weboob, self.gotHousing)
|
|
||||||
self.process.do('fillobj', housing, backends=housing.backend)
|
|
||||||
|
|
||||||
def setPhoto(self, housing, item):
|
def setPhoto(self, housing, item):
|
||||||
if not housing:
|
if not housing:
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,12 @@ class QueryDialog(QDialog):
|
||||||
"""
|
"""
|
||||||
event.ignore()
|
event.ignore()
|
||||||
|
|
||||||
|
def selectComboValue(self, box, value):
|
||||||
|
for i in xrange(box.count()):
|
||||||
|
if box.itemText(i) == str(value):
|
||||||
|
box.setCurrentIndex(i)
|
||||||
|
break
|
||||||
|
|
||||||
def searchCity(self):
|
def searchCity(self):
|
||||||
pattern = unicode(self.ui.cityEdit.text())
|
pattern = unicode(self.ui.cityEdit.text())
|
||||||
self.ui.resultsList.clear()
|
self.ui.resultsList.clear()
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,20 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="nameEdit"/>
|
<widget class="QLineEdit" name="nameEdit"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="typeBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Rent</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Sale</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,12 @@ class Housing(CapBaseObject):
|
||||||
self.add_field('details', dict)
|
self.add_field('details', dict)
|
||||||
|
|
||||||
class Query(CapBaseObject):
|
class Query(CapBaseObject):
|
||||||
|
TYPE_RENT = 0
|
||||||
|
TYPE_SALE = 1
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
CapBaseObject.__init__(self, '')
|
CapBaseObject.__init__(self, '')
|
||||||
|
self.add_field('type', int)
|
||||||
self.add_field('cities', (list,tuple))
|
self.add_field('cities', (list,tuple))
|
||||||
self.add_field('area_min', int)
|
self.add_field('area_min', int)
|
||||||
self.add_field('area_max', int)
|
self.add_field('area_max', int)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue