def build_bot(): """ Constrói a base do bot com todos os scrapers cadastrados Returns: telegram_bot (TelegramBot): Classe do bot """ token = utils.get_config().get(section="telegram", option="BOT_TOKEN") contacts_path = os.path.join(utils.get_data_path(), "contacts_list.json") scraper_list = [ MarinhaScraper( name="CP-CEM 2021", database_path=os.path.join(utils.get_data_path(), "cem2021.json"), url= "https://www.inscricao.marinha.mil.br/marinha/index_concursos.jsp?id_concurso=401", ), MarinhaSMVScraper( name="SMV 2022", database_path=os.path.join(utils.get_data_path(), "smv2022.json"), ), FundepScraper( name="Fundep", database_path=os.path.join(utils.get_data_path(), "fundep.json"), ), CorridasBRScraper( name="CorridasBR", database_path=os.path.join(utils.get_data_path(), "corridasbr.json"), base_url="http://www.corridasbr.com.br/MG/", table_url= "http://www.corridasbr.com.br/MG/por_regiao.asp?regi%E3o=Metropolitana%20de%20Belo%20Horizonte", max_distance=5, ), PCIScraper( name="PCI Concursos", database_path=os.path.join(utils.get_data_path(), "pci.json"), store_size=7, keywords=[ "automacao", "eletrica", "eletricidade", "eletronica analogica", "eletronica digital", "eletrotecnica", "engenharia elet", "engenheiro elet", "marinha", "telecom", ], ignore_words=["estagio", "estagiario", "aprendiz", "suspens"], ), ] telegram_bot = TelegramBot(token=token, scraper_list=scraper_list, contacts_path=contacts_path) return telegram_bot
import time from Concursobo import utils from Concursobo.concursobo import build_bot from apscheduler.schedulers.background import BackgroundScheduler if __name__ == "__main__": """ Runs the pool and send method and send messages only if there is an update """ telegram_bot = build_bot() scheduler = BackgroundScheduler() timezone = utils.get_config().get(section="timezone", option="PYTZ_TIMEZONE") scheduler.configure(timezone=timezone) def job_cem2021(): telegram_bot.auto_check(scraper_name="CP-CEM 2021") def job_smv2022(): telegram_bot.auto_check(scraper_name="SMV 2022") def job_fundep(): telegram_bot.auto_check(scraper_name="Fundep") def job_corridasbr(): telegram_bot.auto_check(scraper_name="CorridasBR") def job_pci():
def scrape_page(self): """ Coleta os dados da página da Fundep """ self.logger.info(msg="Acessando a página...") webpage = requests.get(url=self.url) if webpage.status_code != 200: self.logger.info(msg="Não foi possível acessar a página") return AcquisitionStatus.ERROR self.logger.info(msg="Página acessada, obtendo os dados...") soup = BeautifulSoup(markup=webpage.text, features="html.parser") jobs_info = soup.find_all("li", {"class": "column column-block"}) all_jobs = list() for job in jobs_info: job_title = job.text.split("\n")[1] job_description = "" for p in job.find_all("p"): job_description += p.text job_url = None for url in job.find_all("a"): if "Mais informações" in url.text: job_url = url["href"] job_data = { "title": job_title, "description": job_description, "url": job_url, } all_jobs.append(job_data) self.logger.info(msg=f"{len(all_jobs)} vagas capturadas") timezone = pytz.timezone( zone=utils.get_config().get(section="timezone", option="PYTZ_TIMEZONE") ) current_time = datetime.now(tz=timezone) with open(file=self.db_path, mode="r") as f: stored_data = json.load(f) output_data = { "url": self.url, "acquisition_date": current_time.strftime("%d/%m/%Y %H:%M:%S"), "all_jobs": all_jobs, "last_update": stored_data["last_update"], } self.logger.info( msg="Comparando com a aquisição do dia " + stored_data["acquisition_date"] + "..." ) update_added, update_removed = utils.list_difference( list_A=all_jobs, list_B=stored_data["all_jobs"] ) if len(update_added) == 0 and len(update_removed) == 0: self.logger.info(msg="Nenhuma alteração encontrada") with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UNCHANGED if update_added: self.logger.info(msg=f"{len(update_added)} vagas adicionadas!") if update_added: self.logger.info(msg=f"{len(update_removed)} vagas removidas!") last_update = { "date": current_time.strftime("%d/%m/%Y %H:%M:%S"), "jobs_added": update_added, "jobs_removed": update_removed, } output_data["last_update"] = last_update with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UPDATED
def scrape_page(self): """ Coleta os dados da página do concurso da Marinha Returns: (AcquisitionStatus): Indica o status da aquisição, se houve sucesso e / ou atualização dos dados """ self.logger.info(msg="Acessando a página...") webpage = requests.get(url=self.table_url) if webpage.status_code != 200: self.logger.info(msg="Não foi possível acessar a página") return AcquisitionStatus.ERROR self.logger.info(msg="Página acessada, obtendo os dados...") soup = BeautifulSoup(markup=webpage.text, features="html.parser") tables_soup = soup.find_all(name="table", attrs={"width": "700"}) # Título da página title = tables_soup[0].text.replace("\n", "")[:-1] rows_soup = tables_soup[1].findAll(name="tr", attrs={"height": "40"}) races_list = list() for row_soup in rows_soup: row_data = row_soup.findAll(name="td") race_date = datetime.strptime(row_data[0].text, "%d/%m/%Y") race_city = row_data[1].text.strip() race_title = row_data[2].text.strip() if "km" in row_data[3].text: race_distances = row_data[3].text.replace("km", "").split("/") race_distances = sorted([ float(distance.replace(",", ".")) for distance in race_distances ]) if self.check_distance(race_distances=race_distances) is False: continue distances_str = "/".join([ str(d).replace(".0", "").replace(".", ",") for d in race_distances ]) + "km" else: race_distances = [row_data[3].text] distances_str = "".join(race_distances) race_url = self.base_url + row_data[2].findAll( name="a")[0].attrs["href"] race_data = { "date": race_date, "city": race_city, "title": race_title + " - " + distances_str, "url": race_url, } races_list.append(race_data) self.logger.info(msg=f"{len(races_list)} corridas capturadas") timezone = pytz.timezone(zone=utils.get_config().get( section="timezone", option="PYTZ_TIMEZONE")) current_time = datetime.now(tz=timezone) grouped_races = self.group_races(races_list=races_list) with open(file=self.db_path, mode="r") as f: stored_data = json.load(f) output_data = { "title": title, "url": self.table_url, "acquisition_date": current_time.strftime("%d/%m/%Y %H:%M:%S"), "all_races": grouped_races, "last_update": stored_data["last_update"], } self.logger.info(msg="Comparando com a aquisição do dia " + stored_data["acquisition_date"] + "...") updated_races = self.compare_new_with_old( current_data=grouped_races, stored_data=stored_data["all_races"]) if len(updated_races) == 0: self.logger.info(msg="Nenhuma alteração encontrada") with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UNCHANGED self.logger.info(msg=f"Alterações encontradas!") output_data["last_update"]["date"] = current_time.strftime( "%d/%m/%Y %H:%M:%S") output_data["last_update"]["races_added"] = updated_races with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UPDATED
def scrape_page(self): """ Coleta os dados da página de notícias do PCI Concursos Returns: (AcquisitionStatus): Indica o status da aquisição, se houve sucesso e / ou atualização dos dados """ session = requests.Session() current_page = 1 saved_data = dict() while len(saved_data) < self.store_size: self.logger.info(msg=f"Acessando a página {current_page}...") webpage = session.get(url=self.url + str(current_page)) if webpage.status_code != 200: self.logger.info(msg="Não foi possível acessar a página") return AcquisitionStatus.ERROR self.logger.info( msg=f"Página {current_page} acessada, obtendo os dados...") soup = BeautifulSoup(markup=webpage.text, features="html.parser") page_data = soup.find_all(["h2", "ul"]) news_date = None saved_jobs = list() for data in page_data: date_match = re.match(pattern=r"[0-9]{2}/[0-9]{2}/[0-9]{2}", string=data.text) if "principal" in data.attrs.get("class", list()) and date_match: news_date = datetime.strptime(date_match.string, "%d/%m/%Y") saved_jobs = list() if "noticias" in data.attrs.get( "class", list()) and (news_date is not None): jobs = data.find_all("a") self.logger.info( f"Processando o dia {str(news_date.date())} (" + str(len(jobs)) + " notícias)...") for job in jobs: self.job_scrape(job=job, saved_jobs=saved_jobs, session=session) if saved_jobs: self.logger.info( f"{len(saved_jobs)} notícias encontradas!") if news_date in saved_data: saved_data[news_date].extend(saved_jobs) else: saved_data[news_date] = saved_jobs if len(saved_data) >= self.store_size: break current_page += 1 timezone = pytz.timezone(zone=utils.get_config().get( section="timezone", option="PYTZ_TIMEZONE")) current_time = datetime.now(tz=timezone) with open(file=self.db_path, mode="r") as f: stored_data = json.load(f) all_jobs = self.process_saved_data(saved_data=saved_data) output_data = { "url": self.url, "acquisition_date": current_time.strftime("%d/%m/%Y %H:%M:%S"), "all_jobs": all_jobs, "last_update": stored_data["last_update"], } self.logger.info(msg="Comparando com a aquisição do dia " + stored_data["acquisition_date"] + "...") updated_data = self.compare_new_with_old( current_data=all_jobs, stored_data=stored_data["all_jobs"]) if len(updated_data) == 0: self.logger.info(msg="Nenhuma alteração encontrada") with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UNCHANGED self.logger.info(msg=f"{len(updated_data)} alterações encontradas!") output_data["last_update"] = { "date": current_time.strftime("%d/%m/%Y %H:%M:%S"), "updated_data": updated_data, } with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UPDATED
def scrape_page(self): """ Coleta os dados da página do concurso da Marinha Returns: (AcquisitionStatus): Indica o status da aquisição, se houve sucesso e / ou atualização dos dados """ self.logger.info(msg="Acessando a página...") webpage = requests.get(url=self.url) if webpage.status_code != 200: self.logger.info(msg="Não foi possível acessar a página") return AcquisitionStatus.ERROR self.logger.info(msg="Página acessada, obtendo os dados...") soup = BeautifulSoup(markup=webpage.text, features="html.parser") # Título da página title = soup.find_all(name="h1", class_="page-header")[0].text # Tabela das informações tables_soup = soup.findAll(name="table", class_="views-table cols-0 table table-hover table-striped") message_list = list() for table_soup in tables_soup: rows_soup = table_soup.findAll(name="tr") for row_soup in rows_soup: row_data = row_soup.findAll(name="td") date = re.sub(pattern=r"[\n\t\xa0]", repl="", string=row_data[0].text) message = re.sub(pattern=r"[\n\t\xa0]", repl="", string=row_data[1].text) url = row_data[2].findAll(name="a")[0].attrs["href"] msg_data = { "date": date.strip(), "message": message.strip(), "url": url, } message_list.append(msg_data) self.logger.info(msg=f"{len(message_list)} mensagens capturadas") timezone = pytz.timezone( zone=utils.get_config().get(section="timezone", option="PYTZ_TIMEZONE") ) current_time = datetime.now(tz=timezone) with open(file=self.db_path, mode="r") as f: stored_data = json.load(f) output_data = { "title": title, "url": self.url, "acquisition_date": current_time.strftime("%d/%m/%Y %H:%M:%S"), "messages": message_list, "last_update": stored_data["last_update"], "last_update_date": stored_data["last_update_date"], } self.logger.info( msg="Comparando com a aquisição do dia " + stored_data["acquisition_date"] + "..." ) updated_messages, _ = utils.list_difference( list_A=message_list, list_B=stored_data["messages"] ) if len(updated_messages) == 0: self.logger.info(msg="Nenhuma alteração encontrada") with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UNCHANGED self.logger.info(msg=f"{len(updated_messages)} alterações encontradas!") output_data["last_update"] = updated_messages output_data["last_update_date"] = current_time.strftime("%d/%m/%Y %H:%M:%S") with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UPDATED
def scrape_page(self): """ Coleta os dados da página do concurso da Marinha Returns: (AcquisitionStatus): Indica o status da aquisição, se houve sucesso e / ou atualização dos dados """ self.logger.info(msg="Acessando a página...") webpage = requests.get(url=self.url) if webpage.status_code != 200: self.logger.info(msg="Não foi possível acessar a página") return AcquisitionStatus.ERROR self.logger.info(msg="Página acessada, obtendo os dados...") soup = BeautifulSoup(markup=webpage.text, features="html.parser") # Título da página title = soup.find_all(name="span", class_="header0")[0].text # Data do concurso raw_date_text = webpage.text.split("Data da Prova")[1] split_s = raw_date_text.find("<table") split_e = raw_date_text.find("</table") date_text = raw_date_text[split_s:split_e] date_soup = BeautifulSoup(markup=date_text + "</table>", features="html.parser") exam_date = date_soup.text.replace("\n", "").replace("\t", "").replace("\r", "") # Tabela das informações info_table_config = { "height": "24", "width": "46", "align": "right", "valign": "middle", } info_table_soup = soup.findAll(name="td", attrs=info_table_config) message_list = list() for information in info_table_soup: contents = information.parent.contents info_date = contents[5].get_text()[-8:] info_msg = contents[7].contents[1].contents[0].get_text() msg_data = { "date": info_date, "message": info_msg, "url": "https://www.inscricao.marinha.mil.br/marinha/" + contents[7].contents[1].attrs["href"], } message_list.append(msg_data) self.logger.info(msg=f"{len(message_list)} mensagens capturadas") timezone = pytz.timezone(zone=utils.get_config().get( section="timezone", option="PYTZ_TIMEZONE")) current_time = datetime.now(tz=timezone) with open(file=self.db_path, mode="r") as f: stored_data = json.load(f) output_data = { "title": title, "url": self.url, "acquisition_date": current_time.strftime("%d/%m/%Y %H:%M:%S"), "exam_date": stored_data["exam_date"], "messages": message_list, "last_update": stored_data["last_update"], "last_update_date": stored_data["last_update_date"], } self.logger.info(msg="Comparando com a aquisição do dia " + stored_data["acquisition_date"] + "...") updated_messages, _ = utils.list_difference( list_A=message_list, list_B=stored_data["messages"]) if exam_date != stored_data["exam_date"]: self.logger.info( msg=f"Data do concurso atualizada para: {exam_date}") updated_messages.append({ "date": current_time.strftime("%d/%m/%Y"), "message": f"Data do concurso atualizada para: {exam_date}", "url": self.url, }) output_data["exam_date"] = exam_date if len(updated_messages) == 0: self.logger.info(msg="Nenhuma alteração encontrada") with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UNCHANGED self.logger.info( msg=f"{len(updated_messages)} alterações encontradas!") output_data["last_update"] = updated_messages output_data["last_update_date"] = current_time.strftime( "%d/%m/%Y %H:%M:%S") with open(file=self.db_path, mode="w") as f: json.dump(output_data, f, indent=4) return AcquisitionStatus.UPDATED