Skip to content
Extraits de code Groupes Projets

Comparer les révisions

Les modifications sont affichées comme si la révision source était fusionnée avec la révision cible. En savoir plus sur la comparaison des révisions.

Source

Sélectionner le projet cible
No results found

Cible

Sélectionner le projet cible
  • la-quadrature-du-net/Attrap
  • foggyfrog/Attrap
  • skhwiz/Attrap
  • precambrien/Attrap
  • ketsapiwiq/Attrap
  • Joseki/Attrap
  • kr1p/attrap-pref-12
  • kr1p/attrap-pref-46
  • kr1p/attrap-pi
  • Guinness/Attrap
  • astroidgritty/attrap-pref-84
  • davinov/Attrap
  • maettellite/attrap-pref-01
  • m242/Attrap
  • multi/Attrap
  • mverdeil/Attrap
  • olpo/Attrap
17 résultats
Afficher les modifications
Validations sur la source (2)
import os from Attrap_prefdpt import Attrap_prefdpt
import datetime
import logging
from bs4 import BeautifulSoup
from urllib.parse import unquote
from Attrap import Attrap class Attrap_pref44(Attrap_prefdpt):
logger = logging.getLogger(__name__) # Configuration de la préfecture
class Attrap_pref44(Attrap):
# Config
hostname = 'https://www.loire-atlantique.gouv.fr' hostname = 'https://www.loire-atlantique.gouv.fr'
raa_page = f'{hostname}/Publications/Recueil-des-actes-administratifs-RAA-en-Loire-Atlantique' raa_page = f'{hostname}/Publications/Recueil-des-actes-administratifs-RAA-en-Loire-Atlantique'
user_agent = 'Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0'
full_name = 'Préfecture de la Loire-Atlantique' full_name = 'Préfecture de la Loire-Atlantique'
short_code = 'pref44' short_code = 'pref44'
timezone = 'Europe/Paris' timezone = 'Europe/Paris'
def __init__(self, data_dir): # Configuration des widgets à analyser
super().__init__(data_dir, self.user_agent) Attrap_prefdpt.grey_card['regex']['year'] = '([0-9]{4})'
self.set_sleep_time(30) Attrap_prefdpt.grey_card['regex']['month'] = '([A-Za-zéû]* [0-9]{4})'
Attrap_prefdpt.grey_card['add_year_to_months'] = True
def get_raa(self, keywords):
pages_to_parse = []
# Parfois un RAA est mal catégorisé et se retrouve sur la page racine, donc on la parse
pages_to_parse.append(self.raa_page)
# On détermine quelles pages d'année parser
year_pages_to_parse = []
page_content = self.get_page(self.raa_page, 'get').content
year_pages = self.get_sub_pages(
page_content,
'.fr-card.fr-card--sm.fr-card--grey.fr-enlarge-link div.fr-card__body div.fr-card__content h2.fr-card__title a',
self.hostname,
False
)
for year_page in year_pages:
year = 9999
try:
year = int(year_page['name'].strip())
if year is None:
year = 9999
except Exception as exc:
logger.warning(f"Impossible de deviner l\'année de la page {year_page['name']}")
year = 9999
if year >= self.not_before.year:
year_pages_to_parse.append(year_page['url'])
# Parfois un RAA est mal catégorisé et se retrouve sur la page de l'année, donc on la parse
pages_to_parse.append(year_page['url'])
# Pour chaque année, on cherche les sous-pages de mois
month_pages_to_parse = []
for year_page in year_pages_to_parse:
page_content = self.get_page(year_page, 'get').content
month_pages = self.get_sub_pages(
page_content,
'.fr-card.fr-card--sm.fr-card--grey.fr-enlarge-link div.fr-card__body div.fr-card__content h2.fr-card__title a',
self.hostname,
False
)[::-1]
for month_page in month_pages:
pages_to_parse.append(month_page['url'])
# On parse les pages sélectionnées
elements = self.get_raa_with_pager(
pages_to_parse,
"ul.fr-pagination__list li a.fr-pagination__link.fr-pagination__link--next.fr-pagination__link--lg-label",
self.hostname
)[::-1]
self.parse_raa(elements, keywords)
self.mailer()
def get_raa_elements(self, page_content):
elements = []
# On récupère chaque carte avec un RAA
for card in BeautifulSoup(page_content, 'html.parser').select('div.fr-card.fr-card--horizontal div.fr-card__body div.fr-card__content'):
# On récupère le lien
links = card.select('h2.fr-card__title a.fr-card__link.menu-item-link')
# On récupère la date
dates_raw = card.select('div.fr-card__end p.fr-card__detail')
# Si on a toutes les infos, on continue
if links and links[0] and dates_raw and dates_raw[0]:
a = links[0]
date_raw = dates_raw[0]
if a.get('href') and a['href'].endswith('.pdf'):
if a['href'].startswith('/'):
url = f"{self.hostname}{a['href']}"
else:
url = a['href']
url = unquote(url)
name = a.get_text().strip()
date = datetime.datetime.strptime(date_raw.get_text().replace('Publié le', '').strip(), '%d/%m/%Y')
raa = Attrap.RAA(url, date, name, timezone=self.timezone)
elements.append(raa)
return elements
...@@ -22,7 +22,8 @@ class Attrap_prefdpt(Attrap): ...@@ -22,7 +22,8 @@ class Attrap_prefdpt(Attrap):
'link_to_raa': False, 'link_to_raa': False,
'autodetect_links_to_raa': True, 'autodetect_links_to_raa': True,
'follow_link_on_unrecognised_date': True, 'follow_link_on_unrecognised_date': True,
'exclude': [] 'exclude': [],
'add_year_to_months': False
} }
white_card = { white_card = {
'regex': { 'regex': {
...@@ -37,7 +38,8 @@ class Attrap_prefdpt(Attrap): ...@@ -37,7 +38,8 @@ class Attrap_prefdpt(Attrap):
'link_to_raa': False, 'link_to_raa': False,
'autodetect_links_to_raa': True, 'autodetect_links_to_raa': True,
'follow_link_on_unrecognised_date': True, 'follow_link_on_unrecognised_date': True,
'exclude': [] 'exclude': [],
'add_year_to_months': False
} }
# Liste des widgets à analyser (sera remplie au moment de l'initialisation, mais peut être surchargée par la classe de préfecture de département) # Liste des widgets à analyser (sera remplie au moment de l'initialisation, mais peut être surchargée par la classe de préfecture de département)
...@@ -57,7 +59,7 @@ class Attrap_prefdpt(Attrap): ...@@ -57,7 +59,7 @@ class Attrap_prefdpt(Attrap):
class DptWidget: class DptWidget:
"""Une classe représentant un widget sur le site d'une préfecture de département.""" """Une classe représentant un widget sur le site d'une préfecture de département."""
def __init__(self, name, regex=None, css_path=None, link_to_raa=False, autodetect_links_to_raa=True, follow_link_on_unrecognised_date=True, exclude=[]): def __init__(self, name, regex=None, css_path=None, link_to_raa=False, autodetect_links_to_raa=True, follow_link_on_unrecognised_date=True, exclude=[], add_year_to_months=False):
self.name = name self.name = name
self.regex = regex self.regex = regex
self.css_path = css_path self.css_path = css_path
...@@ -65,6 +67,7 @@ class Attrap_prefdpt(Attrap): ...@@ -65,6 +67,7 @@ class Attrap_prefdpt(Attrap):
self.autodetect_links_to_raa = autodetect_links_to_raa self.autodetect_links_to_raa = autodetect_links_to_raa
self.follow_link_on_unrecognised_date = follow_link_on_unrecognised_date self.follow_link_on_unrecognised_date = follow_link_on_unrecognised_date
self.exclude = exclude self.exclude = exclude
self.add_year_to_months = add_year_to_months
def has_css_path(self, key): def has_css_path(self, key):
return self.css_path and self.css_path.get(key, None) is not None return self.css_path and self.css_path.get(key, None) is not None
...@@ -94,15 +97,30 @@ class Attrap_prefdpt(Attrap): ...@@ -94,15 +97,30 @@ class Attrap_prefdpt(Attrap):
self.follow_link_on_unrecognised_date = follow_link_on_unrecognised_date self.follow_link_on_unrecognised_date = follow_link_on_unrecognised_date
self.exclude = exclude self.exclude = exclude
def add_url(self, url, date=None):
if date and date.year == 9999:
date = None
self.page_urls_to_parse.append([url, date])
def get_urls_to_parse(self):
urls = []
for url in self.page_urls_to_parse:
urls.append(url[0])
return urls
def __init__(self, data_dir): def __init__(self, data_dir):
"""Une classe générique permettant d'analyser les préfectures de département en fonction de certains paramètres.""" """Une classe générique permettant d'analyser les préfectures de département en fonction de certains paramètres."""
super().__init__(data_dir, self.user_agent) super().__init__(data_dir, self.user_agent)
self.set_sleep_time(self.pref_sleep_time) self.set_sleep_time(self.pref_sleep_time)
self.page_urls_to_parse = []
if isinstance(self.raa_page, str): if isinstance(self.raa_page, str):
self.raa_page = [self.raa_page] self.add_url(self.raa_page)
self.page_urls_to_parse = self.raa_page else:
for url in self.raa_page:
self.add_url(url)
self.elements = [] self.elements = []
# On ajoute les cartes grises et blanches à la liste des widgets à parser # On ajoute les cartes grises et blanches à la liste des widgets à parser
...@@ -115,7 +133,8 @@ class Attrap_prefdpt(Attrap): ...@@ -115,7 +133,8 @@ class Attrap_prefdpt(Attrap):
link_to_raa=self.grey_card['link_to_raa'], link_to_raa=self.grey_card['link_to_raa'],
autodetect_links_to_raa=self.grey_card['autodetect_links_to_raa'], autodetect_links_to_raa=self.grey_card['autodetect_links_to_raa'],
follow_link_on_unrecognised_date=self.grey_card['follow_link_on_unrecognised_date'], follow_link_on_unrecognised_date=self.grey_card['follow_link_on_unrecognised_date'],
exclude=self.grey_card['exclude'] exclude=self.grey_card['exclude'],
add_year_to_months=self.grey_card['add_year_to_months']
) )
) )
...@@ -128,15 +147,16 @@ class Attrap_prefdpt(Attrap): ...@@ -128,15 +147,16 @@ class Attrap_prefdpt(Attrap):
link_to_raa=self.white_card['link_to_raa'], link_to_raa=self.white_card['link_to_raa'],
autodetect_links_to_raa=self.white_card['autodetect_links_to_raa'], autodetect_links_to_raa=self.white_card['autodetect_links_to_raa'],
follow_link_on_unrecognised_date=self.white_card['follow_link_on_unrecognised_date'], follow_link_on_unrecognised_date=self.white_card['follow_link_on_unrecognised_date'],
exclude=self.white_card['exclude'] exclude=self.white_card['exclude'],
add_year_to_months=self.white_card['add_year_to_months']
) )
) )
def get_raa(self, keywords): def get_raa(self, keywords):
while not self.page_urls_to_parse == []: while not self.page_urls_to_parse == []:
page_url = self.page_urls_to_parse[-1] page_url = self.page_urls_to_parse[-1]
page_content = self.get_page(page_url, 'get').content # On récupère le HTML de la page page_content = self.get_page(page_url[0], 'get').content # On récupère le HTML de la page
self.parse_widgets(page_content) # On parse les cartes self.parse_widgets(page_url, page_content) # On parse les cartes
self.parse_select_widgets(page_url, page_content) # On parse les menus déroulants self.parse_select_widgets(page_url, page_content) # On parse les menus déroulants
for element in self.get_raa_elements(page_content): # On cherche les RAA for element in self.get_raa_elements(page_content): # On cherche les RAA
self.elements.append(element) self.elements.append(element)
...@@ -145,7 +165,7 @@ class Attrap_prefdpt(Attrap): ...@@ -145,7 +165,7 @@ class Attrap_prefdpt(Attrap):
self.parse_raa(self.elements[::-1], keywords) self.parse_raa(self.elements[::-1], keywords)
self.mailer() self.mailer()
def parse_widgets(self, page_content): def parse_widgets(self, page_url, page_content):
# Pour chaque widget paramétré qui n'est pas de type select, on le cherche sur la page # Pour chaque widget paramétré qui n'est pas de type select, on le cherche sur la page
for widget in self.widgets: for widget in self.widgets:
cards = [] cards = []
...@@ -166,7 +186,7 @@ class Attrap_prefdpt(Attrap): ...@@ -166,7 +186,7 @@ class Attrap_prefdpt(Attrap):
False False
) )
for card in cards: for card in cards:
if card['url'] not in self.page_urls_to_parse and card['name'].strip() not in widget.exclude: if card['url'] not in self.get_urls_to_parse() and card['name'].strip() not in widget.exclude:
date = None date = None
date_is_correct = False date_is_correct = False
...@@ -178,13 +198,18 @@ class Attrap_prefdpt(Attrap): ...@@ -178,13 +198,18 @@ class Attrap_prefdpt(Attrap):
date_is_correct = True date_is_correct = True
# Si un regex de mois est spécifié et qu'aucune date correcte n'a été trouvée, on teste avec le regex de mois sur le titre # Si un regex de mois est spécifié et qu'aucune date correcte n'a été trouvée, on teste avec le regex de mois sur le titre
if widget.has_regex('month') and not date_is_correct: if widget.has_regex('month') and (not date or date.year == 9999):
date = Attrap.guess_date(card['name'].strip(), widget.get_regex('month')).replace(day=1) # On ajoute l'année au nom du mois à tester si configuré dans le widget
if widget.add_year_to_months and page_url[1]:
month = card['name'].strip()+' '+str(page_url[1].year)
else:
month = card['name'].strip()
date = Attrap.guess_date(month, widget.get_regex('month')).replace(day=1)
if date >= self.not_before.replace(day=1) and date.year < 9999: if date >= self.not_before.replace(day=1) and date.year < 9999:
date_is_correct = True date_is_correct = True
# Si un chemin CSS vers les détails du widget est spécifié et qu'aucune date correcte n'a été trouvée, on tente de parser la date présente dans les détails # Si un chemin CSS vers les détails du widget est spécifié et qu'aucune date correcte n'a été trouvée, on tente de parser la date présente dans les détails
if widget.has_css_path('details') and not date_is_correct: if widget.has_css_path('details') and (not date or date.year == 9999):
try: try:
date = datetime.datetime.strptime(card['details'].replace('Publié le ', '').strip(), '%d/%m/%Y') date = datetime.datetime.strptime(card['details'].replace('Publié le ', '').strip(), '%d/%m/%Y')
if date >= self.not_before: if date >= self.not_before:
...@@ -201,7 +226,7 @@ class Attrap_prefdpt(Attrap): ...@@ -201,7 +226,7 @@ class Attrap_prefdpt(Attrap):
else: else:
# Si une date a été trouvée, on regarde s'il faut ajouter l'URL à la liste des pages à parser # Si une date a été trouvée, on regarde s'il faut ajouter l'URL à la liste des pages à parser
if date_is_correct or ((date is None or date.year == 9999) and widget.follow_link_on_unrecognised_date): if date_is_correct or ((date is None or date.year == 9999) and widget.follow_link_on_unrecognised_date):
self.page_urls_to_parse.append(card['url']) self.add_url(card['url'], date)
def parse_select_widgets(self, page_url, page_content): def parse_select_widgets(self, page_url, page_content):
for select_widget in self.select_widgets: for select_widget in self.select_widgets:
...@@ -223,7 +248,7 @@ class Attrap_prefdpt(Attrap): ...@@ -223,7 +248,7 @@ class Attrap_prefdpt(Attrap):
# on demande au serveur les détails du RAA # on demande au serveur les détails du RAA
if (date.year < 9999 and date >= self.not_before) or (date.year == 9999 and select_widget.follow_link_on_unrecognised_date): if (date.year < 9999 and date >= self.not_before) or (date.year == 9999 and select_widget.follow_link_on_unrecognised_date):
page_content = self.get_page( page_content = self.get_page(
page_url, page_url[0],
'post', 'post',
{ {
select['id']: option['value'] select['id']: option['value']
......