import os, re import subprocess import logging import requests from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions from pyvirtualdisplay import Display from pdfminer.high_level import extract_text logger = logging.getLogger(__name__) class RAAspotter: class RAA: url = "" date = "" name = "" filename = "" def __init__(self, url, date, name, filename): if not url == "": self.url = url if not date == "": self.date = date if not name == "": self.name = name if not filename == "": self.filename = filename def __init__(self, data_dir, user_agent=""): logger.debug('Initialisation de RAAspotter') self.user_agent = user_agent self.session = requests.Session() self.data_dir = data_dir # On démarre le navigateur def get_session(self, url, wait_element=""): webdriver_options = webdriver.ChromeOptions() webdriver_options.add_argument("--no-sandbox") webdriver_options.add_argument("--disable-extensions") webdriver_options.add_argument("--disable-gpu") webdriver_options.add_argument("--disable-dev-shm-usage") webdriver_options.add_argument("--use_subprocess") webdriver_options.add_argument("--disable-blink-features=AutomationControlled") if not self.user_agent == "": webdriver_options.add_argument(f"--user-agent={self.user_agent}") webdriver_options.add_argument("--headless") webdriver_options.add_argument("--window-size=1024,768") display = Display(visible=False, size=(1024, 768)) display.start() browser = webdriver.Chrome(options=webdriver_options) # Téléchargement de l'URL browser.get(url) if not wait_element == "": # On attend que le navigateur ait passé les tests anti-robots et que le contenu s'affiche WebDriverWait(browser, 120).until(expected_conditions.presence_of_element_located((By.ID, wait_element))) page_content = browser.page_source # On récupère les cookies du navigateur pour les réutiliser plus tard for cookie in browser.get_cookies(): self.session.cookies.set(cookie['name'], cookie['value']) self.session.headers.update({'User-Agent': self.user_agent}) # On arrête le navigateur browser.quit() display.stop() return page_content def print_output(data): print(data) data = data.replace('\033[92m', '') data = data.replace('\033[0m', '') data = data.replace('\033[1m', '') f = open(os.path.dirname(os.path.abspath(__file__))+'/output.log','a') f.write(data+"\n") f.close() def download_file(self, raa): try: os.makedirs(os.path.dirname(self.data_dir+raa.filename), exist_ok=True) file = self.session.get(raa.url) f = open(self.data_dir+raa.filename,'wb') f.write(file.content); f.close() except (requests.exceptions.ConnectionError, requests.exceptions.ChunkedEncodingError): logger.warning(f'ATTENTION: la connexion a été interrompue pendant le téléchargement de {raa.url}, nouvelle tentative...') self.download_file(raa) except Exception as exc: logger.warning(f'ATTENTION: Impossible de télécharger le fichier {raa.url}: {exc}') def get_txt_file(filename): return re.sub('(\.pdf)$', '.txt', filename) def parse_pdf(self, raa, keywords): if not os.path.isfile(self.data_dir+raa.filename): logger.warning(f'ATTENTION: le fichier {raa.filename} n\'existe pas') else: text = extract_text(self.data_dir+raa.filename) found = False for keyword in keywords: if re.search(keyword, text, re.IGNORECASE|re.MULTILINE): if not found: RAAspotter.print_output(f'\033[92m{raa.name}\033[0m ({raa.date})') found = True RAAspotter.print_output(f' Le terme \033[1m{keyword}\033[0m a été trouvé.') # Écrit le texte du PDF dans un fichier texte pour une analyse future, puis supprime le PDF f = open(RAAspotter.get_txt_file(self.data_dir+raa.filename),'w') f.write(text) f.close() os.remove(self.data_dir+raa.filename) if found: RAAspotter.print_output('') def ocr(self, raa, retry_on_failure=True): cmd = ['ocrmypdf', '-l', 'eng+fra', '--output-type', 'pdfa', '--redo-ocr', '--skip-big', '500' , self.data_dir+raa.filename, self.data_dir+raa.filename] logger.debug(f'Lancement de ocrmypdf: {cmd}') try: output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as exc: if exc.returncode == 2 and retry_on_failure: logger.warning('ATTENTION : Le fichier n\'est pas un PDF correct, nouvelle tentative de le télécharger') self.download_file(raa) self.ocr(raa,False) elif (not exc.returncode == 6) and (not exc.returncode == 10): logger.warning('ATTENTION : Impossible d\'OCRiser le document', exc.returncode, exc.output) def parse_raa(self, elements, keywords): for raa in elements: # Si le fichier n'a pas déjà été parsé, on le télécharge et on le parse if not os.path.isfile(RAAspotter.get_txt_file(self.data_dir+raa.filename)): logger.info(f'Nouveau fichier : {raa.name} ({raa.date}). URL : {raa.url}') self.download_file(raa) self.ocr(raa, True) self.parse_pdf(raa, keywords) def get_raa(self, page_content): logger.error('Cette fonction doit être surchargée')