class TorConnect: def __init__(self, alone=None, host_db=None, user_db=None, password_db=None, database=None, telegram_chat_id=None, telegram_token=None, order=None, number=None, list=None, list_file=None, ignoredate=None): self.ignoredate = ignoredate self.number = number self.order = order self.list = list self.list_file = list_file self.host_db = host_db self.user_db = user_db self.password_db = password_db self.telegram_chat_id = telegram_chat_id self.telegram_token = telegram_token self.database_name = database self.database = DataBase( host_db=self.host_db, user_db=self.user_db, password_db=self.password_db, database=self.database_name, ) self.logger = logging.getLogger('Class:TorConnect') self.telegram = Telegram() self.date = datetime.now() self.session = requests.session() self.desktop_agents = [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Firefox/60.0' ] self.proxies = { 'http': 'socks5h://localhost:9050', } self.alone = alone @property def headers(self): return { 'User-Agent': choice(self.desktop_agents), 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' } @property def start(self): self.selection() def selection(self): lastsevendays = datetime.strptime( time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime()), '%Y-%m-%dT%H:%M:%S') - timedelta(days=7) lastfourteendays = datetime.strptime( time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime()), '%Y-%m-%dT%H:%M:%S') - timedelta(days=14) if self.list is not None: with open(self.list_file, 'r') as outputfile: self.logger.info(' Aplicando REGEX. Aguarde...') regex = re.compile( "[A-Za-z0-9]{0,12}\.?[A-Za-z0-9]{12,50}\.onion") for lines in outputfile.readlines(): rurls = lines \ .replace('\xad', '') \ .replace('\n', '') \ .replace("http://", '') \ .replace("https://", '') \ .replace(r'\s', '') \ .replace('\t', '') xurl = regex.match(rurls) if xurl is not None: externalURL = xurl.group() self.logger.debug( ' Comparando a URL digitada com o que está no banco de dados.' ) compare_url = self.database.compare_url( url=externalURL) if compare_url: self.logger.debug( ' A url {url} já existe no banco de dados.'. format(url=externalURL)) else: self.database.save_url(url=externalURL, source=1) for id, source_id, url, status, created_in, last_date in self.database.select_alone( alone=externalURL): if self.ignoredate: self.crawler(id=id, url=url) else: if status == 1: self.logger.info( ' A url {url} com o status de ONLINE já foi vista.' .format(url=url)) if last_date is not None: if last_date <= lastfourteendays: self.logger.info( ' Já faz mais de duas semanas que a url {url} com o status de ONLINE foi vista pela ultima vez, uma nova verificação será feita.' .format(url=url)) self.crawler(id=id, url=url) else: self.crawler(id=id, url=url) elif status == 0: if last_date is not None: if last_date <= lastsevendays: self.logger.info( ' Já faz mais de duas semanas que a url {url} com o status de OFFILINE foi vista pela ultima vez, uma nova verificação será feita.' .format(url=url)) self.crawler(id=id, url=url) else: self.logger.info( ' A url {url} nunca foi vista, uma tentativa será feita agora..' .format(url=url)) self.crawler(id=id, url=url) elif self.order: self.logger.info( ' Você selecionou a opção para ordenar pela coluna {number}.'. format(number=self.number)) for id, source_id, url, status, created_in, last_date in self.database.select( )[int(self.number)::int(self.number)]: if status == 1: self.logger.info( ' A url {url} já foi vista, será verificado a ultima vez que a mesma foi visitada.' .format(url=url)) if last_date is not None: if last_date <= lastfourteendays: self.logger.info( ' Já faz mais de duas semanas que a url {url} com o status de ONLINE foi vista pela ultima vez, uma nova verificação será feita.' .format(url=url)) self.crawler(id=id, url=url) else: self.crawler(id=id, url=url) elif status == 0: if last_date is not None: if last_date <= lastsevendays: self.logger.info( ' Já faz mais de duas semanas que a url {url} com o status de OFFILINE foi vista pela ultima vez, uma nova verificação será feita.' .format(url=url)) self.crawler(id=id, url=url) else: self.logger.info( ' A url {url} nunca foi vista, uma tentativa será feita agora..' .format(url=url)) self.crawler(id=id, url=url) elif self.alone is not None: self.logger.info(' Você selecionou o CRAWLER para apenas uma URL.') if '.onion' in self.alone: if len(self.alone.split(',')) == 1: self.logger.debug( ' Comparando a URL digitada com o que está no banco de dados.' ) compare_url = self.database.compare_url(url=self.alone) if compare_url: self.logger.debug( ' A url {url} já existe no banco de dados.'.format( url=self.alone)) else: self.database.save_url(url=self.alone, source=1) for id, source_id, url, status, created_in, last_date in self.database.select_alone( alone=self.alone): self.crawler(id=id, url=url) else: self.logger.info( ' Parece que você colocou mais de uma URL, será realizado CRAWLER, uma de cada vez.' ) for alones in self.alone.split(','): self.logger.debug( ' Comparando a URL digitada com o que está no banco de dados.' ) compare_url = self.database.compare_url(url=alones) if compare_url: self.logger.debug( ' A url {url} já existe no banco de dados.'. format(url=alones)) else: self.database.save_url(url=alones, source=1) for id, source_id, url, status, created_in, last_date in self.database.select_alone( alone=alones): self.crawler(id=id, url=url) else: self.logger.error( ' OPSS... Isso que você digitou não é uma url da rede TOR.\n\n\n' ) else: self.logger.info( ' Você selecionou o Crawçer padrão, seguindo pela ordem do ID.' ) for id, source_id, url, status, created_in, last_date in self.database.select( ): if status == 1: if last_date <= lastfourteendays: self.logger.info( ' Já faz mais de duas semanas que a url {url} com o status de ONLINE foi vista pela ultima vez, uma nova verificação será feita.' .format(url=url)) self.crawler(id=id, url=url) elif status == 0: if last_date <= lastfourteendays: self.logger.info( ' Já faz mais de duas semanas que a url {url} com o status de OFFILINE foi vista pela ultima vez, uma nova verificação será feita.' .format(url=url)) self.crawler(id=id, url=url) else: self.logger.info( ' A url {url} nunca foi vista, uma tentativa será feita agora..' .format(url=url)) self.crawler(id=id, url=url) def moreurls(self, url=None, default=None): self.logger.info(' Conectando em {}. Aguarde...'.format(url)) fullmoreurl = None if url is not None: replace_url = url.replace('http://', '').replace('\n', '').replace('\s', '') try: request = self.session.get('http://{}'.format(replace_url), proxies=self.proxies, headers=self.headers, timeout=500) if request.status_code == 200: pages = [] soup = BeautifulSoup(request.content, features="lxml") try: for raw in soup.find('body').findAll(): mosturl = str(raw.get('href')) if raw.get('href') is not None: if 'http://' in mosturl: if '.onion' in mosturl: if url in mosturl: fullmoreurl = mosturl.replace( 'http://', '') elif 'https://' in mosturl: if '.onion' in mosturl: if url in mosturl: fullmoreurl = mosturl.replace( 'https://', '') else: if ' ' in mosturl: pass elif "'" in mosturl: pass elif '"' in mosturl: pass elif '(' in mosturl: pass else: if '..' in mosturl: if default is not None: fullmoreurl = '{0}/{1}'.format(default, mosturl) \ .replace('//', '/') else: fullmoreurl = '{0}/{1}'.format(url, mosturl) \ .replace('//', '/') else: if default is not None: fullmoreurl = '{0}/{1}'.format(default, mosturl) \ .replace('//', '/') else: fullmoreurl = '{0}/{1}'.format(url, mosturl) \ .replace('//', '/') if fullmoreurl is not None: pages.append(fullmoreurl) except AttributeError as e: self.logger.error( ' OPSS... Parece que não tem texto nenhum nessa página.\n{e}' .format(e=e)) pass return pages else: self.logger.error(' Não consegui conectar na url') except (requests.exceptions.ConnectionError, requests.exceptions.ChunkedEncodingError, requests.exceptions.ReadTimeout, requests.exceptions.InvalidURL) as e: self.logger.error( ' Não consegui conectar na url, porque ocorreu um erro.\n{e}' .format(e=e)) def crawler_text(self, url=None): try: if url is not None: request_pages = self.session.get('http://{}'.format(url), proxies=self.proxies, headers=self.headers, timeout=500) self.logger.debug(' Conectando em {url} - {status}'.format( url=url, status=request_pages.status_code)) if request_pages.status_code == 200: soup = BeautifulSoup(request_pages.content, features="lxml") #text = soup_page.findAll(text=True) for s in soup(['script', 'style']): s.decompose() return ' '.join(soup.stripped_strings) except (requests.exceptions.ConnectionError, requests.exceptions.ChunkedEncodingError, requests.exceptions.ReadTimeout, requests.exceptions.TooManyRedirects) as e: pass class TimeoutError(Exception): pass def timeout(seconds=10, error_message=os.strerror(errno.ETIME)): def decorator(func): def _handle_timeout(signum, frame): raise TimeoutError(error_message) def wrapper(*args, **kwargs): signal.signal(signal.SIGALRM, _handle_timeout) signal.alarm(seconds) try: result = func(*args, **kwargs) finally: signal.alarm(0) return result return wraps(func)(wrapper) return decorator @timeout(30) def screenshot(self, namescreenshot=None, url=None): try: os.system( "google-chrome --headless --no-sandbox --disable-gpu --proxy-server=socks://127.0.0.1:9050 --screenshot=VigilantOnion/media/sites/cover/{namescreenshot}.png http://{url}" .format(namescreenshot=namescreenshot, url=url)) except TimeoutError: self.logger.error( ' Não foi possível realizar o screenshot da url {url}.'.format( url=url)) def crawler(self, id, url): text = [] key = None type = None status = 0 self.logger.info( ' Iniciando o Crawler na url {url}...'.format(url=url)) if url is not None: self.startscritp = time.time() namescreenshot = url.replace('.', '') self.logger.debug( ' Tentando conexão na url {url}, para os proximos passos.'. format(url=url)) try: request_pages = self.session.get('http://{}'.format(url), proxies=self.proxies, headers=self.headers, timeout=100) if request_pages.status_code == 200: self.logger.info( ' Fazendo uma screenshot da pagina inicial da url {url}.' .format(url=url)) self.screenshot(namescreenshot=namescreenshot, url=url) if self.moreurls(url=url) is not None: for pages in self.moreurls(url=url): url_pages = pages \ .replace('\xad', '') \ .replace('\n', '') \ .replace("http://", '') \ .replace("https://", '') \ .replace(r'\s', '') \ .replace('\t', '') \ .replace('//', '/') try: request_pages_more = self.session.get( 'http://{}'.format(url_pages), proxies=self.proxies, headers=self.headers, timeout=100) if request_pages_more.status_code == 200: if self.database.compare_more( url=url_pages): self.logger.debug( ' A url {url} já está no banco de dados.' .format(url=url_pages)) else: self.database.save_more(url=url_pages, status=1) if self.database.check_url_more_id( url_id=id, more_id=self.database. return_id_more( url=url_pages)[0][0]): self.logger.debug( ' A url {url} já está no banco de dados.' .format(url=url_pages)) else: self.database.save_url_more_id( url_id=id, more_id=self.database. return_id_more( url=url_pages)[0][0]) check_sub_pages = self.moreurls( url=url_pages, default=url) if check_sub_pages is not None: for sub_pages in check_sub_pages: url_pages_more = sub_pages \ .replace('\xad', '') \ .replace('\n', '') \ .replace("http://", '') \ .replace("https://", '') \ .replace(r'\s', '') \ .replace('\t', '') \ .replace('//', '/') try: request_pages_more = self.session.get( 'http://{}'.format( url_pages_more), proxies=self.proxies, headers=self.headers, timeout=100) if request_pages_more.status_code == 200: if self.database.compare_more( url=url_pages_more ): self.logger.debug( ' A url {url} já está no banco de dados.' .format( url= url_pages_more) ) else: self.database.save_more( url=url_pages_more, status=1) if self.database.check_url_more_id( url_id=id, more_id=self. database. return_id_more( url= url_pages_more )[0][0]): self.logger.debug( ' A url {url} já está no banco de dados.' .format( url= url_pages_more )) else: self.database.save_url_more_id( url_id=id, more_id=self. database. return_id_more( url= url_pages_more )[0][0]) else: self.logger.error( ' Por Algum motivo, não consegui conectar na URL {url}' .format( url=url_pages_more )) except (requests.exceptions. ConnectionError, requests.exceptions. ChunkedEncodingError, requests.exceptions. ReadTimeout, requests.exceptions. InvalidURL) as e: self.logger.error( ' Um erro ocorreu.\n\n{error}\n.' .format(error=e)) pass except (requests.exceptions.ConnectionError, requests.exceptions.ChunkedEncodingError, requests.exceptions.ReadTimeout, requests.exceptions.InvalidURL) as e: self.logger.error( ' Um erro ocorreu.\n\n{error}\n'.format( error=e)) pass self.logger.info( ' Obtendo todas as informações, das páginas salvas.') if self.database.return_id_urls_more(id=id): for id_pages in self.database.return_id_urls_more( id=id): pagination = self.database.return_url_more( id=id_pages[0]) filelog = "/tmp/{}".format( url.replace('onion', 'lonion')) if not os.path.exists(filelog): arquivo = open(filelog, 'w', encoding="utf8") arquivo.close() text_crawler = str( self.crawler_text(url=pagination[0][0])) if text_crawler is not None: arquivo = open(filelog, 'r', encoding="utf8") conteudo = arquivo.readlines() conteudo.append(text_crawler) arquivo = open(filelog, 'w', encoding="utf8") arquivo.writelines(conteudo) arquivo.close() counter_category = collections.Counter() with open(filelog, 'r') as a: self.logger.info(' Definindo a categoria do site.') for linha in a: linha = linha.split('\n') for id_categorie, term in self.database.return_categorie_term( ): if term.lower() in str(linha).lower(): type = id_categorie counter_category[term] += 1 self.logger.info(' Procurando por keywords.') for linha in a: linha = linha.split('\n') for id_keyword, company, term in self.database.return_keyword( ): if term.lower() in str(linha).lower(): key = id_keyword self.database.save_search_keyword( url_id=id, company_id=company) break if key is not None: fim = time.time() self.database.save_categorie(id=id, status=1, type=type) alert = "KEYWORD:\n\nNew keyword:\nSite:{url}\nStatus: 200\nkeyword:{key}\nTime:{time}\n".format( url=url, key=key, time=int(fim - self.startscritp), ) self.telegram.send(alert) if type is not None: fim = time.time() cover = "sites/cover/{namescreenshot}.png".format( namescreenshot=namescreenshot) name_type = max(counter_category.most_common()) save_type = self.database.return_keyword_id( term=name_type[0])[0][0] self.database.save_categorie(id=id, status=1, type=int(save_type), cover=cover) alert = "New site with 200 return found:\nSite:{url}\nStatus: 200\nType:{type}\nTime:{time}\n".format( url=url, type=int(save_type), time=int(fim - self.startscritp), ) self.telegram.send(alert) os.remove(filelog) else: fim = time.time() cover = "sites/cover/{namescreenshot}.png".format( namescreenshot=namescreenshot) self.database.save_categorie(id=id, status=1, type=1, cover=cover) alert = "New site with 200 return found:\nSite:{url}\nStatus: 200\nType:{type}\nTime:{time}\n".format( url=url, type=1, time=int(fim - self.startscritp), ) self.telegram.send(alert) os.remove(filelog) else: fim = time.time() cover = "sites/cover/{namescreenshot}.png".format( namescreenshot=namescreenshot) self.database.save_categorie(id=id, status=1, type=1, cover=cover) alert = "New site with 200 return found:\nSite:{url}\nStatus: 200\nType:{type}\nTime:{time}\n".format( url=url, type=1, time=int(fim - self.startscritp), ) self.telegram.send(alert) else: self.logger.error( ' Por Algum motivo, não consegui conectar na URL, vou salvar como offline, para uma nova tentativa ser realizada, no proximo loop.' ) self.database.save_categorie_404(id=id, status=0) except (requests.exceptions.ConnectionError, requests.exceptions.ChunkedEncodingError, requests.exceptions.ReadTimeout, requests.exceptions.InvalidURL) as e: self.logger.error( ' Um erro ocorreu.\n\n{error}\nPor conta desse erro vou salvar no banco de dados como offline.' .format(error=e)) self.database.save_categorie_404(id=id, status=0) else: self.logger.debug( ' Alguma URL entrou como None, melhor dar uma olhada no banco de dados.\n Talvez executar a limpeza funcione.' )
class ExternalListAPI: def __init__( self, file=None, host_db=None, user_db=None, password_db=None, database=None): self.host_db = host_db self.user_db = user_db self.password_db = password_db self.database_name = database self.database = DataBase( host_db = self.host_db, user_db = self.user_db, password_db = self.password_db, database = self.database_name, ) self.source = 'Pastebin' logging.basicConfig(level=logging.INFO) compare_sorce = self.database.compare_source(source=self.source) if compare_sorce: pass else: self.database.save_source(source=self.source) self.logger = logging.getLogger('Class:ExternalListAPI') self.file = file @property def start(self): self.database.replaces() self.getExternal() def getExternal(self): self.logger.info(' Fazendo comparação da lista de URLS com o banco de dados. AGUARDE..') with open(self.file , 'r') as outputfile: self.logger.info(' Aplicando REGEX. Aguarde...') regex = re.compile("[A-Za-z0-9]{0,12}\.?[A-Za-z0-9]{12,50}\.onion") for lines in outputfile.readlines(): rurls = lines \ .replace('\xad', '') \ .replace('\n', '') \ .replace("http://", '') \ .replace("https://", '') \ .replace(r'\s', '') \ .replace('\t', '') xurl = regex.match(rurls) if xurl is not None: compare_sorce = self.database.compare_source(source=self.source) compare_url = self.database.compare_url(url=xurl.group()) if compare_url: self.logger.debug(' A url {url} já existe no banco de dados.'.format(url=xurl.group())) else: self.database.save_url(url=xurl.group(), source=compare_sorce[0][0])