diff --git a/modules/apec/browser.py b/modules/apec/browser.py
index b4810ac1..f9852793 100644
--- a/modules/apec/browser.py
+++ b/modules/apec/browser.py
@@ -17,50 +17,97 @@
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see .
-from weboob.deprecated.browser.decorators import id2url
-from weboob.deprecated.browser import Browser
-import urllib
-from .pages import SearchPage, AdvertPage
-from .job import ApecJobAdvert
+from weboob.browser.profiles import Profile
+from weboob.browser import PagesBrowser, URL
+from .pages import IdsPage, OffrePage
__all__ = ['ApecBrowser']
-class ApecBrowser(Browser):
- PROTOCOL = 'https'
- DOMAIN = 'www.apec.fr'
- ENCODING = 'ISO-8859-1'
+class JsonProfile(Profile):
+ def setup_session(self, session):
+ session.headers["Content-Type"] = "application/json"
- PAGES = {
- 'https://cadres.apec.fr/liste-offres-emploi-cadres/71____(.*?)_(.*?)_(.*?)_(.*?)_(.*?)_(.*?)_(.*?)___offre-d-emploi.html': SearchPage,
- 'https://cadres.apec.fr/MesOffres/RechercheOffres/ApecRechercheOffre.jsp\?keywords=(.*?)': SearchPage,
- 'https://cadres.apec.fr/offres-emploi-cadres/offres-emploi-cadres/\d*_\d*_\d*_(.*?)________(.*?).html(.*?)': AdvertPage,
- }
+
+class ApecBrowser(PagesBrowser):
+ BASEURL = 'https://cadres.apec.fr'
+ PROFILE = JsonProfile()
+
+ start = 0
+ json_count = URL('/cms/webservices/rechercheOffre/count', IdsPage)
+ json_ids = URL('/cms/webservices/rechercheOffre/ids', IdsPage)
+ json_offre = URL('/cms/webservices/offre/public\?numeroOffre=(?P<_id>.*)', OffrePage)
+
+ def create_parameters(self, pattern='', fonctions='[]', lieux='[]', secteursActivite='[]', typesContrat='[]', typesConvention='[]', niveauxExperience='[]', salaire_min='', salaire_max='', date_publication='', start=0, range=20):
+
+ if date_publication:
+ date_publication = ',"anciennetePublication":%s' % (date_publication)
+
+ if salaire_max:
+ salaire_max = ',"salaireMaximum":%s' % (salaire_max)
+
+ if salaire_min:
+ salaire_min = ',"salaireMinimum":%s' % (salaire_min)
+
+ return '{"activeFiltre":true,"motsCles":"%s","fonctions":%s,"lieux":%s,"secteursActivite":%s,"typesContrat":%s,"typesConvention":%s,"niveauxExperience":%s%s%s%s,"sorts":[{"type":"SCORE","direction":"DESCENDING"}],"pagination":{"startIndex":%s,"range":%s},"typeClient":"CADRE"}' % (pattern, fonctions, lieux, secteursActivite, typesContrat, typesConvention, niveauxExperience, salaire_min, salaire_max, date_publication, start, range)
def search_job(self, pattern=None):
- self.location('https://cadres.apec.fr/MesOffres/RechercheOffres/ApecRechercheOffre.jsp?keywords=%s'
- % urllib.quote_plus(pattern.encode(self.ENCODING)))
- assert self.is_on_page(SearchPage)
- return self.page.iter_job_adverts()
+ data = self.create_parameters(pattern=pattern)
+ count = self.json_count.go(data=data).get_adverts_number()
+ self.start = 0
+ if count:
+ ids = self.json_ids.go(data=data).iter_job_adverts(pattern=pattern,
+ fonctions='[]',
+ lieux='[]',
+ secteursActivite='[]',
+ typesContrat='[]',
+ typesConvention='[]',
+ niveauxExperience='[]',
+ salaire_min='',
+ salaire_max='',
+ date_publication='',
+ start=self.start,
+ count=count,
+ range=20)
+ for _id in ids:
+ yield self.json_offre.go(_id=_id.id).get_job_advert()
- def advanced_search_job(self, region=None, fonction=None, secteur=None, salaire=None, contrat=None, limit_date=None, level=None):
- self.location(
- 'https://cadres.apec.fr/liste-offres-emploi-cadres/71____%s_%s_%s_%s_%s_%s_%s___offre-d-emploi.html'
- % (
- region,
- fonction,
- secteur,
- salaire,
- level,
- limit_date,
- contrat
- ))
- assert self.is_on_page(SearchPage)
- return self.page.iter_job_adverts()
+ def get_job_advert(self, _id, advert=None):
+ return self.json_offre.go(_id=_id).get_job_advert(obj=advert)
- @id2url(ApecJobAdvert.id2url)
- def get_job_advert(self, url, advert):
- self.location(url)
- assert self.is_on_page(AdvertPage)
- return self.page.get_job_advert(url, advert)
+ def advanced_search_job(self, region='', fonction='', secteur='', salaire='', contrat='', limit_date='', level=''):
+ salaire_max = ''
+ salaire_min = ''
+
+ if salaire:
+ s = salaire.split('|')
+ salaire_max = s[1]
+ salaire_min = s[0]
+
+ data = self.create_parameters(fonctions='[%s]' % fonction,
+ lieux='[%s]' % region,
+ secteursActivite='[%s]' % secteur,
+ typesContrat='[%s]' % contrat,
+ niveauxExperience='[%s]' % level,
+ salaire_min=salaire_min,
+ salaire_max=salaire_max,
+ date_publication=limit_date)
+
+ count = self.json_count.go(data=data).get_adverts_number()
+ self.start
+ if count:
+ ids = self.json_ids.go(data=data).iter_job_adverts(pattern='',
+ fonctions='[%s]' % fonction,
+ lieux='[%s]' % region,
+ secteursActivite='[%s]' % secteur,
+ typesContrat='[%s]' % contrat,
+ niveauxExperience='[%s]' % level,
+ salaire_min=salaire_min,
+ salaire_max=salaire_max,
+ date_publication=limit_date,
+ start=self.start,
+ count=count,
+ range=20)
+ for _id in ids:
+ yield self.json_offre.go(_id=_id).get_job_advert()
diff --git a/modules/apec/module.py b/modules/apec/module.py
index e1d1f866..9db1a869 100644
--- a/modules/apec/module.py
+++ b/modules/apec/module.py
@@ -17,13 +17,12 @@
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see .
-
+from weboob.capabilities.job import BaseJobAdvert
from weboob.tools.backend import Module, BackendConfig
from weboob.capabilities.job import CapJob
from weboob.tools.ordereddict import OrderedDict
from weboob.tools.value import Value
from .browser import ApecBrowser
-from .job import ApecJobAdvert
__all__ = ['ApecModule']
@@ -38,63 +37,174 @@ class ApecModule(Module, CapJob):
BROWSER = ApecBrowser
places_choices = OrderedDict([(k, u'%s' % (v)) for k, v in sorted({
- '00|': u'-- Indifférent --',
- '01|700': u'Alsace',
- '02|701': u'Aquitaine',
- '03|702': u'Auvergne',
- '04|703': u'Basse-Normandie',
- '05|704': u'Bourgogne',
- '06|705': u'Bretagne',
- '07|706': u'Centre',
- '08|707': u'Champagne',
- '09|20': u'Corse',
- '10|99712': u'France Outre-Mer',
- '11|709': u'Franche-Comté',
- '12|710': u'Haute-Normandie',
- '13|711': u'Ile-de-France',
- '14|712': u'Languedoc-Roussillon',
- '15|713': u'Limousin',
- '16|714': u'Lorraine',
- '17|715': u'Midi-Pyrénées',
- '18|716': u'Nord-Pas-de-Calais',
- '19|720': u'PACA',
- '20|717': u'Pays de La Loire',
- '21|718': u'Picardie',
- '22|719': u'Poitou-Charentes',
- '23|721': u'Rhône-Alpes',
- '24|99109': u'Allemagne',
- '25|99106': u'Estonie',
- '26|99108': u'Lituanie',
- '27|99116': u'République Tchèque',
- '28|99110': u'Autriche',
- '29|99105': u'Finlande',
- '30|99137': u'Luxembourg',
- '31|99114': u'Roumanie',
- '32|99131': u'Belgique',
- '33|99126': u'Grèce',
- '34|99144': u'Malte',
- '35|99132': u'Royaume Uni',
- '36|99111': u'Bulgarie',
- '37|99112': u'Hongrie',
- '38|99135': u'Pays Bas',
- '39|99117': u'Slovaquie',
- '40|99254': u'Chypre',
- '41|99136': u'Irlande',
- '42|99122': u'Pologne',
- '43|99145': u'Slovénie',
- '44|99101': u'Danemark',
- '45|99127': u'Italie',
- '46|99139': u'Portugal',
- '47|99104': u'Suède',
- '48|99134': u'Espagne',
- '49|99107': u'Lettonie',
- '50|99700': u'UE Hors France',
- '51|99702': u'Amérique du Nord',
- '52|99715': u'Afrique',
- '53|99711': u'Océanie',
- '54|99701': u'Europe Hors UE',
- '55|99714': u'Amérique Latine',
- '56|99716': u'Asie',
+ '001|99700': u'UE Hors France',
+ '002|99126': u'..Grèce',
+ '003|99132': u'..Royaume Uni',
+ '004|99134': u'..Espagne',
+ '005|99136': u'..Irlande',
+ '006|99139': u'..Portugal',
+ '007|99254': u'..Chypre',
+ '008|99127': u'..Italie',
+ '009|99131': u'..Belgique',
+ '010|99135': u'..Pays Bas',
+ '011|99137': u'..Luxembourg',
+ '012|99144': u'..Malte',
+ '013|99145': u'..Slovénie',
+ '014|99101': u'..Danemark',
+ '015|99104': u'..Suède',
+ '016|99105': u'..Finlande',
+ '017|99106': u'..Estonie',
+ '018|99107': u'..Lettonie',
+ '019|99108': u'..Lituanie',
+ '020|99109': u'..Allemagne',
+ '021|99110': u'..Autriche',
+ '022|99111': u'..Bulgarie',
+ '023|99112': u'..Hongrie',
+ '024|99114': u'..Roumanie',
+ '025|99116': u'..République Tchèque',
+ '026|99117': u'..Slovaquie',
+ '027|99119': u'..Croatie',
+ '028|99122': u'..Pologne',
+ '029|799': u'France',
+ '030|711': u'..Ile-de-France',
+ '031|75': u'....Paris',
+ '032|77': u'....Seine-et-Marne',
+ '033|78': u'....Yvelines',
+ '034|91': u'....Essonne',
+ '035|92': u'....Hauts-de-Seine',
+ '036|93': u'....Seine-Saint-Denis',
+ '037|94': u'....Val-de-Marne',
+ '038|95': u'....Val-d\'Oise',
+ '039|703': u'..Basse-Normandie',
+ '040|14': u'....Calvados',
+ '041|50': u'....Manche',
+ '042|61': u'....Orne',
+ '043|705': u'..Bretagne',
+ '044|22': u'....Côtes d\'Armor',
+ '045|29': u'....Finistère',
+ '046|35': u'....Ille-et-Vilaine',
+ '047|56': u'....Morbihan',
+ '048|706': u'..Centre',
+ '049|18': u'....Cher',
+ '050|28': u'....Eure-et-Loir',
+ '051|36': u'....Indre',
+ '052|37': u'....Indre-et-Loire',
+ '053|41': u'....Loir-et-Cher',
+ '054|45': u'....Loiret',
+ '055|710': u'..Haute-Normandie',
+ '056|27': u'....Eure',
+ '057|76': u'....Seine-Maritime',
+ '058|717': u'..Pays de La Loire',
+ '059|44': u'....Loire-Atlantique',
+ '060|49': u'....Maine-et-Loire',
+ '061|53': u'....Mayenne',
+ '062|72': u'....Sarthe',
+ '063|85': u'....Vendée',
+ '064|700': u'..Alsace',
+ '065|67': u'....Bas-Rhin',
+ '066|68': u'....Haut-Rhin',
+ '067|704': u'..Bourgogne',
+ '068|21': u'....Côte d\'Or',
+ '069|58': u'....Nièvre',
+ '070|71': u'....Saône-et-Loire',
+ '071|89': u'....Yonne',
+ '072|707': u'..Champagne',
+ '073|8': u'....Ardennes',
+ '074|10': u'....Aube',
+ '075|51': u'....Marne',
+ '076|52': u'....Haute-Marne',
+ '077|709': u'..Franche-Comté',
+ '078|25': u'....Doubs',
+ '079|39': u'....Jura',
+ '080|70': u'....Haute-Saône',
+ '081|90': u'....Territoire de Belfort',
+ '082|714': u'..Lorraine',
+ '083|54': u'....Meurthe-et-Moselle',
+ '084|55': u'....Meuse',
+ '085|57': u'....Moselle',
+ '086|88': u'....Vosges',
+ '087|716': u'..Nord-Pas-de-Calais',
+ '088|59': u'....Nord',
+ '089|62': u'....Pas-de-Calais',
+ '090|718': u'..Picardie',
+ '091|2': u'....Aisne',
+ '092|60': u'....Oise',
+ '093|80': u'....Somme',
+ '094|20': u'..Corse',
+ '095|750': u'....Corse du Sud',
+ '096|751': u'....Haute-Corse',
+ '097|702': u'..Auvergne',
+ '098|3': u'....Allier',
+ '099|15': u'....Cantal',
+ '100|43': u'....Haute-Loire',
+ '101|63': u'....Puy-de-Dôme',
+ '102|720': u'..PACA',
+ '103|4': u'....Alpes-de-Haute-Provence',
+ '104|5': u'....Hautes-Alpes',
+ '105|6': u'....Alpes-Maritimes',
+ '106|13': u'....Bouches-du-Rhône',
+ '107|83': u'....Var',
+ '108|84': u'....Vaucluse',
+ '109|721': u'..Rhône-Alpes',
+ '110|1': u'....Ain',
+ '111|7': u'....Ardèche',
+ '112|26': u'....Drôme',
+ '113|38': u'....Isère',
+ '114|42': u'....Loire',
+ '115|69': u'....Rhône',
+ '116|73': u'....Savoie',
+ '117|74': u'....Haute-Savoie',
+ '118|701': u'..Aquitaine',
+ '119|24': u'....Dordogne',
+ '120|33': u'....Gironde',
+ '121|40': u'....Landes',
+ '122|47': u'....Lot-et-Garonne',
+ '123|64': u'....Pyrénées-Atlantiques',
+ '124|712': u'..Languedoc-Roussillon',
+ '125|11': u'....Aude',
+ '126|30': u'....Gard',
+ '127|34': u'....Hérault',
+ '128|48': u'....Lozère',
+ '129|66': u'....Pyrénées-Orientales',
+ '130|713': u'..Limousin',
+ '131|19': u'....Corrèze',
+ '132|23': u'....Creuse',
+ '133|87': u'....Haute-Vienne',
+ '134|715': u'..Midi-Pyrénées',
+ '135|9': u'....Ariège',
+ '136|12': u'....Aveyron',
+ '137|31': u'....Haute-Garonne',
+ '138|32': u'....Gers',
+ '139|46': u'....Lot',
+ '140|65': u'....Hautes-Pyrénées',
+ '141|81': u'....Tarn',
+ '142|82': u'....Tarn-et-Garonne',
+ '143|719': u'..Poitou-Charentes',
+ '144|16': u'....Charente',
+ '145|17': u'....Charente-Maritime',
+ '146|79': u'....Deux-Sèvres',
+ '147|86': u'....Vienne',
+ '148|99712': u'..France Outre-Mer',
+ '149|99519': u'....Terres Australes et Antarctiques Françaises',
+ '150|97100': u'....Guadeloupe',
+ '151|97200': u'....Martinique',
+ '152|97300': u'....Guyane',
+ '153|97400': u'....La Réunion',
+ '154|97500': u'....Saint-Pierre-et-Miquelon',
+ '155|97600': u'....Mayotte',
+ '156|98300': u'....Polynésie Française',
+ '157|98600': u'....Wallis et Futuna',
+ '158|98800': u'....Nouvelle Calédonie',
+ '159|97800': u'....Saint-Martin',
+ '160|97700': u'....Saint-Barthélémy',
+ '161|102099': u'International',
+ '162|99715': u'..Afrique',
+ '163|99716': u'..Asie',
+ '164|99700': u'..UE Hors France',
+ '165|99701': u'..Europe Hors UE',
+ '166|99702': u'..Amérique du Nord',
+ '167|99711': u'..Océanie',
+ '168|99714': u'..Amérique Latine',
}.iteritems())])
fonction_choices = OrderedDict([(k, u'%s' % (v)) for k, v in sorted({
@@ -191,18 +301,18 @@ class ApecModule(Module, CapJob):
type_contrat_choices = OrderedDict([(k, u'%s' % (v)) for k, v in sorted({
' ': u'-- Indifférent --',
- '143694': u'CDI',
- '143695': u'CDD',
- '143696': u'Travail Temporaire',
+ '101888': u'CDI',
+ '101887': u'CDD',
+ '101889': u'Interim',
}.iteritems())])
salary_choices = OrderedDict([(k, u'%s' % (v)) for k, v in sorted({
' ': u'-- Indifférent --',
- '101839': u'Moins de 35 K€',
- '101840': u'Entre 35 et 49 K€',
- '101841': u'Entre 50 et 69 K€',
- '101842': u'Entre 70 et 90 K€',
- '101843': u'Plus de 90 K€',
+ '0|35': u'Moins de 35 K€',
+ '35|50': u'Entre 35 et 49 K€',
+ '50|70': u'Entre 50 et 69 K€',
+ '70|90': u'Entre 70 et 90 K€',
+ '90|1000': u'Plus de 90 K€',
}.iteritems())])
date_choices = OrderedDict([(k, u'%s' % (v)) for k, v in sorted({
@@ -214,9 +324,9 @@ class ApecModule(Module, CapJob):
}.iteritems())])
level_choices = OrderedDict([(k, u'%s' % (v)) for k, v in sorted({
- ' ': u'-- Indifférent --',
- '101846': u'Débutant',
- '101848': u'Expérimenté',
+ '101882': u'Tous niveaux d\'expérience',
+ '101881': u'Débutant',
+ '101883': u'Expérimenté',
}.iteritems())])
CONFIG = BackendConfig(Value('place', label=u'Lieu', choices=places_choices, default=''),
@@ -228,9 +338,8 @@ class ApecModule(Module, CapJob):
Value('level', label=u'Expérience', choices=level_choices, default=''))
def search_job(self, pattern=None):
- with self.browser:
- for job_advert in self.browser.search_job(pattern=pattern):
- yield job_advert
+ for job_advert in self.browser.search_job(pattern=pattern):
+ yield self.fill_obj(job_advert)
def decode_choice(self, choice):
splitted_choice = choice.split('|')
@@ -247,13 +356,19 @@ class ApecModule(Module, CapJob):
contrat=self.config['contrat'].get(),
limit_date=self.config['limit_date'].get(),
level=self.config['level'].get()):
- yield job_advert
+ yield self.fill_obj(job_advert)
def get_job_advert(self, _id, advert=None):
- with self.browser:
- return self.browser.get_job_advert(_id, advert)
+ job_advert = self.browser.get_job_advert(_id, advert)
+ return self.fill_obj(job_advert)
- def fill_obj(self, advert, fields):
- self.get_job_advert(advert.id, advert)
+ def fill_obj(self, advert, fields=None):
+ if advert.contract_type in self.type_contrat_choices:
+ advert.contract_type = self.type_contrat_choices[advert.contract_type]
- OBJECTS = {ApecJobAdvert: fill_obj}
+ if advert.experience in self.level_choices:
+ advert.experience = self.level_choices[advert.experience]
+
+ return advert
+
+ OBJECTS = {BaseJobAdvert: fill_obj}
diff --git a/modules/apec/pages.py b/modules/apec/pages.py
index c8c3a295..ecaaa0a0 100644
--- a/modules/apec/pages.py
+++ b/modules/apec/pages.py
@@ -16,67 +16,63 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see .
+import requests
+
+from weboob.browser.elements import ItemElement, method, DictElement
+from weboob.browser.pages import JsonPage, pagination
+from weboob.browser.filters.standard import DateTime, Format, Regexp
+from weboob.browser.filters.json import Dict
+from weboob.browser.filters.html import CleanHTML
+from weboob.capabilities.job import BaseJobAdvert
+from weboob.capabilities.base import NotAvailable
-from weboob.deprecated.browser import Page
-from weboob.tools.html import html2text
-import dateutil.parser
-import re
+class IdsPage(JsonPage):
-from .job import ApecJobAdvert
+ def get_adverts_number(self):
+ return self.doc['totalCount']
+
+ @pagination
+ @method
+ class iter_job_adverts(DictElement):
+ item_xpath = 'resultats'
+
+ def next_page(self):
+ self.page.browser.start += self.env['range']
+ if self.page.browser.start <= self.env['count']:
+ data = self.page.browser.create_parameters(pattern=self.env['pattern'],
+ fonctions=self.env['fonctions'],
+ lieux=self.env['lieux'],
+ secteursActivite=self.env['secteursActivite'],
+ typesContrat=self.env['typesContrat'],
+ typesConvention=self.env['typesConvention'],
+ niveauxExperience=self.env['niveauxExperience'],
+ salaire_min=self.env['salaire_min'],
+ salaire_max=self.env['salaire_max'],
+ date_publication=self.env['date_publication'],
+ start=self.page.browser.start,
+ range=self.env['range'])
+
+ return requests.Request("POST", self.page.url, data=data)
+
+ class item(ItemElement):
+ klass = BaseJobAdvert
+ obj_id = Regexp(Dict('@uriOffre'), '.*=(.*)')
-class SearchPage(Page):
- def iter_job_adverts(self):
- re_id_title = re.compile('/offres-emploi-cadres/\d*_\d*_\d*_(.*?)_(.*?)_(.*?)_(.*?)_(.*?)_(.*?)_(.*?)_(.*?)_(.*?).html', re.DOTALL)
- divs = self.document.getroot().xpath("//div[@class='boxContent offre']") + self.document.getroot().xpath("//div[@class='boxContent offre even']")
- for div in divs:
- a = self.parser.select(div, 'div/div/h3/a', 1, method='xpath')
- _id = u'%s/%s' % (re_id_title.search(a.attrib['href']).group(1), re_id_title.search(a.attrib['href']).group(9))
- advert = ApecJobAdvert(_id)
- advert.title = u'%s' % re_id_title.search(a.attrib['href']).group(9).replace('-', ' ')
- l = self.parser.select(div, 'h4', 1).text.split('-')
- advert.society_name = u'%s' % l[0].strip()
- advert.place = u'%s' % l[-1].strip()
- date = self.parser.select(div, 'div/div/div', 1, method='xpath')
- advert.publication_date = dateutil.parser.parse(date.text_content().strip()[8:]).date()
- yield advert
+class OffrePage(JsonPage):
+ @method
+ class get_job_advert(ItemElement):
+ klass = BaseJobAdvert
-
-class AdvertPage(Page):
- def get_job_advert(self, url, advert):
- re_id_title = re.compile('/offres-emploi-cadres/\d*_\d*_\d*_(.*?)________(.*?).html(.*?)', re.DOTALL)
- if advert is None:
- _id = u'%s/%s' % (re_id_title.search(url).group(1), re_id_title.search(url).group(2))
- advert = ApecJobAdvert(_id)
- advert.title = re_id_title.search(url).group(2).replace('-', ' ')
-
- description = self.document.getroot().xpath("//div[@class='contentWithDashedBorderTop marginTop boxContent']/div")[0]
- advert.description = html2text(self.parser.tostring(description))
-
- advert.job_name = advert.title
-
- trs = self.document.getroot().xpath("//table[@class='noFieldsTable']/tr")
- for tr in trs:
- th = self.parser.select(tr, 'th', 1, method='xpath')
- td = self.parser.select(tr, 'td', 1, method='xpath')
- if u'Date de publication' in u'%s' % th.text_content():
- advert.publication_date = dateutil.parser.parse(td.text_content()).date()
- elif u'Société' in u'%s' % th.text_content() and not advert.society_name:
- society_name = td.text_content()
- a = self.parser.select(td, 'a', method='xpath')
- if a:
- advert.society_name = u'%s' % society_name.replace(a[0].text_content(), '').strip()
- else:
- advert.society_name = society_name.strip()
- elif u'Type de contrat' in u'%s' % th.text_content():
- advert.contract_type = u'%s' % td.text_content().strip()
- elif u'Lieu' in u'%s' % th.text_content():
- advert.place = u'%s' % td.text_content()
- elif u'Salaire' in u'%s' % th.text_content():
- advert.pay = u'%s' % td.text_content()
- elif u'Expérience' in u'%s' % th.text_content():
- advert.experience = u'%s' % td.text_content()
-
- advert.url = url
- return advert
+ obj_id = Dict('numeroOffre')
+ obj_title = Dict('intitule')
+ obj_description = CleanHTML(Dict('texteHtml'))
+ obj_job_name = Dict('intitule')
+ obj_publication_date = DateTime(Dict('datePublication'))
+ obj_society_name = Dict('nomCommercialEtablissement', default=NotAvailable)
+ obj_contract_type = Dict('idNomTypeContrat')
+ obj_place = Dict('lieuTexte')
+ obj_pay = Dict('salaireTexte')
+ obj_experience = Dict('idNomNiveauExperience')
+ obj_url = Format('https://cadres.apec.fr/home/mes-offres/recherche-des-offres-demploi/liste-des-offres-demploi/detail-de-loffre-demploi.html?numIdOffre=%s', Dict('numeroOffre'))