def select_telegram_group(): ''' ''' # Collega il client Telegram with tg_functions.connect_telegram_client( password_manager.tg_phone, password_manager.tg_api_id, password_manager.tg_api_hash) as tg_client: # Ottiene tutte le conversazioni a cui il profilo è connesso list_conversations = tg_functions.get_all_conversations( tg_client, only_groups=True) # Menu di selezione del gruppo da analizzare print(colored('[TELEGRAM]', 'cyan') + ' Selezione gruppo da analizzare:') i = 0 for conv in list_conversations: conv_name = generic.only_ASCII(conv[0].title).strip() print( colored('[', 'red') + str(i) + colored(']', 'red') + ' {}'.format(conv_name)) i += 1 # Lascia selezionare all'utente il gruppo da analizzare print(colored('[TELEGRAM]', 'cyan') + ' Inserisci il numero del gruppo da analizzare: ', end='') # Senza ritorno a capo per mettere l'imput sulla stessa riga conv_index = input() # I colori ANSI non funzionano con input() target_group = list_conversations[int(conv_index)] group_name = generic.only_ASCII(target_group[0].title).strip() print( colored('[TELEGRAM]', 'cyan') + ' E\' stato selezionato il gruppo: {}'.format(group_name)) return target_group
def login(self, username, password): ''' Esegue il login a Instagram usando le credenziali Params: @username: Nome utente dell'account Instagram a cui connettersi @password: Password dell'account Instagram a cui connettersi Return: True se la connessione é avvenuta con successo, False altrimenti ''' # Se é giá istanziato termina l'oggetto e lo ricrea if self.is_initialized: self.terminate() if self._connect_instagram_client(username, password, anonymous=False): self.is_initialized = True self.is_logged = True if self._logger is not None: self._logger.info( 'Instagram client correctly started (user {})'.format( generic.only_ASCII(username))) return True else: return False
def find_user_by_keywords(self, *keywords, max_profiles=10): ''' Cerca dei profili Instagram in base alle parole chiave usate Params: @keyords: Nome utente dell'utente da trovare @max_profiles: NUmero massimo di profili da ottenere Return: Lista di profili individuati ''' try: # Unisce le keywords keywords = [str(i) for i in keywords if i is not None] keyword = ' '.join(keywords).strip() if keyword == '': return [] # Ricerca i profili results = instaloader.TopSearchResults(self._ig_client.context, keyword) profiles = [profile for profile in results.get_profiles()] # Limita il numero di profili if len(profiles) > max_profiles: profiles = profiles[:10] if self._logger is not None: self._logger.info('Found {} profiles with keywords {}'.format( len(profiles), generic.only_ASCII(keyword))) return profiles except Exception as ex: self._manage_error(WEBDRIVER_GENERIC_ERROR, ex) return []
def _select_telegram_group(): ''' Elenca tutti i gruppi a cui l'utente sta partecipando e gli permette di selezionarne uno Return: Gruppo selezionato (Telethon entity) o None se si vuole riprendere una sessione precedente ''' # Collega il client Telegram with tg_functions.connect_telegram_client(password_manager.tg_phone, password_manager.tg_api_id, password_manager.tg_api_hash) as tg_client: # Ottiene tutte le conversazioni a cui il profilo è connesso list_conversations = tg_functions.get_all_conversations( tg_client, only_groups=True) # Menu di selezione del gruppo da analizzare print(colored('[TELEGRAM]', 'cyan') + ' Selection of Telegram group to analyze:') i = 0 for conv in list_conversations: conv_name = generic.only_ASCII(conv[0].title).strip() print( colored( '[', 'red') + str(i) + colored( ']', 'red') + ' {}'.format(conv_name)) i += 1 # Lascia selezionare all'utente il gruppo da analizzare print( colored( '[TELEGRAM]', 'cyan') + ' Enter the index of the group to be analyzed: ', end='') # Senza ritorno a capo per mettere l'imput sulla stessa riga conv_index = input() # I colori ANSI non funzionano con input() target_group = list_conversations[int(conv_index - 1)][0] group_name = generic.only_ASCII(target_group.title).strip() print(colored('[TELEGRAM]', 'cyan') + ' Selected Telegram group: {}'.format(group_name)) _scrape_logger.info('Selected Telegram group: {}'.format(group_name)) return target_group
def get_location_history(self, ig_profile): ''' Ottiene tutti i geotag dei post per uno specifico profilo Instagram. E' necessario essere loggati per usare questa funzione. Params: @ig_profile: Profilo Instagram (Instaloader) di cui recuperare i geotag Return: Lista di localitá (classes.location) individuate ''' # Variabili locali locations_list = [] # E' necessario essere loggati per usare questa funzione if not self.is_logged: self._manage_error(USER_NOT_LOGGED, None) return [] # Ottiene l'elenco dei post del profilo Instagram try: post_list = ig_profile.get_posts() except PrivateProfileNotFollowedException as ex: self._manage_error(PRIVATE_PROFILE_NOT_FOLLOWED, ex) return [] except Exception as ex: self._manage_error(WEBDRIVER_GENERIC_ERROR, ex) return [] # Salva i geotag dei media selezionati post_with_location = [ post for post in post_list if post.location is not None ] for post in post_with_location: loc = location.location() # Ottiene la locazione dalle coordinate if post.location.lat is not None and post.location.lng is not None: loc.from_coordinates(post.location.lat, post.location.lng, post.date_utc) locations_list.append(loc) elif post.location.name is not None: loc.from_name(post.location.name, post.date_utc) locations_list.append(loc) # Ordina la lista dalla locazione più recente a quella meno recente locations_list.sort(key=lambda loc: loc.utc_time, reverse=True) if self._logger is not None: self._logger.info('Found {} locations for user {}'.format( len(locations_list), generic.only_ASCII(ig_profile.username))) return locations_list
def find_user_by_keywords(self, *keywords, max_users=10): ''' Cerca dei profili Twitter compatibili con le parole chiave specificate. Params: @keywords: Parole chiave da utilizzare per la ricerca @max_users [5]: Massimo numero di utenti da ricercare Return: Lista di profili Twitter (profiles.twitter_profile) ''' # Variabili locali usernames = [] tw_profiles = [] if not self.is_initialized: ex = exceptions.WebDriverNotInitialized( 'The WebDriver is not initialized, please call the init() function' ) self._manage_error(WEBDRIVER_NOT_INITIALIZED, ex) return None # Compone l'URL da utilizzare per la ricerca keys = [str(s).strip() for s in keywords if s is not None] search_string = ' '.join(keys) if search_string == '': return [] self._driver.get(SEARCH_PEOPLE_URL.format(search_string)) # Ricerca gli username degli utenti individuati usernames_elms = self._driver.find_elements(By.XPATH, RESULTS_USERNAMES_XPATH) # Ottiene i link degli utenti usernames = [elm.text for elm in usernames_elms] # Limita il massimo numero di profili da cercare if len(usernames) > max_users: usernames = usernames[:max_users] # Ottiene i dati dei profili for username in usernames: p = self.find_user_by_username(username) tw_profiles.append(p) if self._logger is not None: self._logger.info('Found {} profiles with the keywords: {}'.format( len(tw_profiles), generic.only_ASCII(','.join(keys)))) return tw_profiles
def _connect_instagram_client(self, username, password, anonymous=True): ''' Crea e connette un client Instagram. Se anonymous = True le credenziali non verrano usate (possono essere qualunque valore) Params: @username: Nome utente del proprio account Instagram @password: Password del proprio account Instagram @anonymous [True]: Connessione in maniera anonima (senza credenziali) Return: True se la connessione é avvenuta correttamente, False altrimenti ''' # Crea il client ig_client = instaloader.Instaloader(quiet=True, download_videos=False, download_comments=False, compress_json=True, max_connection_attempts=1) # File di salvataggio della sessione ig_session_file = 'instagram_session.session' # Se è stato specificato un client anonimo non vengono specificate le # credenziali if anonymous: self._ig_client = ig_client if self._logger is not None: self._logger.info('Successfully connected anonymously') return True # Se esiste un file di sessione già configurato lo carica if os.path.exists(ig_session_file) and not anonymous: ig_client.load_session_from_file(username, ig_session_file) else: try: ig_client.login(username, password) ig_client.save_session_to_file(ig_session_file) except Exception as ex: self._manage_error(LOGIN_GENERIC_ERROR, ex) return False self._ig_client = ig_client if self._logger is not None: self._logger.info('Successfully connected to user {}'.format( generic.only_ASCII(username))) return True
def _scrape_twitter(people, save_people_dir): ''' Esegue l'associazione dei profili delle persone a Twitter Params: @people: Lista di classes.person a cui associare un profilo Twitter @save_people_dir: Cartella dove salvare i file profilo ''' # Istanzia lo scraper per Twitter tw_scraper = tw_functions.tw_scraper(_tw_logger) _scrape_logger.info('Search for Twitter users') for p in tqdm(people, 'Search for Twitter users'): # Gestisce l'interruzione della ricerca da parte dell'utente if _terminate_program: tw_scraper.terminate() _end_program() _scrape_logger.debug( 'Search user TW profiles with profile ID {}, name {} {}'.format( p.id, p.first_name, p.last_name)) # Verifica se già esiste un profilo Facebook if not len( p.get_profiles('Twitter')) > 0 and tw_scraper.is_initialized: # Ricerca del profilo Twitter result = p.find_twitter_profile(tw_scraper, 'italia') if result > 0: tqdm.write( colored('[Twitter]', 'white', 'on_cyan') + generic.only_ASCII( ' Identified compatible Twitter profile for {} {} ({} references)' .format(p.first_name, p.last_name, result))) # Salva i risultati save_path = os.path.join(save_people_dir, '{}.person'.format(p.id)) pickle.dump(p, open(save_path, 'wb'), protocol=pickle.HIGHEST_PROTOCOL) database.set_person_checked(_db_path, p.id, 'Twitter')
def find_user_by_keywords(self, *keywords, max_users=5): ''' Cerca dei profili Facebook compatibili con le parole chiave specificate. E' necessario aver effettuato il login. Params: @keywords: Parole chiave da utilizzare per la ricerca @max_users [5]: Massimo numero di utenti da ricercare Return: Lista di profili Facebook (profiles.facebook_profile) ''' # Variabili locali usernames = [] fb_profiles = [] links = [] # Controlla se il profilo è bloccato if self.is_blocked: return [] # Bisogna essere loggati per cercare gli utenti if not self.is_logged: ex = exceptions.UserNotLogged('In order to use this function the user need to be logged to Facebook') self._manage_error(USER_NOT_LOGGED, ex) return [] # Compone l'URL da utilizzare per la ricerca keys = [str(s).strip() for s in keywords if s is not None] search_string = '%20'.join(keys) if search_string == '': return [] self._driver.get(SEARCH_URL.format(search_string)) time.sleep(SLEEP_TIME_MEDIUM) self._request_manager() # Ricerca i link degli utenti individuati links = self._driver.find_elements( By.CLASS_NAME, FB_SEARCH_PEOPLE_LINK_CLASSNAME) # Ottiene i link degli utenti links = [link.get_attribute('href')for link in links] # Ottiene gli username degli utenti for link in links: username = link.replace(BASE_URL, '') index_question_mark = username.find('?') # Valore non trovato, possibile cambiamento nelle URL di Facebook if index_question_mark == -1: continue else: username = username[:index_question_mark] # Un qualche utente standard? if 'profile.php' in usernames: usernames.remove('profile.php') # Aggiunge il nome utente usernames.append(username) # Limita il massimo numero di profili da cercare if len(usernames) > max_users: usernames = usernames[:max_users] # Ottiene i dati dei profili for username in usernames: # Esce dal ciclo se il profilo è bloccato if self.is_blocked: break # Saltiamo la verifica perchè sappiamo già che i profili esistono p = self.find_user_by_username(username, skip_verification=True) if p is not None: fb_profiles.append(p) time.sleep(SLEEP_TIME_LONG) if self._logger is not None: self._logger.info( 'Found {} profiles with the keywords: {}'.format( len(fb_profiles), generic.only_ASCII(','.join(keys)))) return fb_profiles
def _scrape_facebook_instagram(people, save_people_dir): ''' Esegue l'associazione dei profili delle persone a Facebook e Instagram. Vengono eseguite le associazioni in maniera alternata, così da limitare i casi di blocco degli account o di attesa per troppe richieste. Params: @people: Lista di classes.person a cui associare un profilo Twitter @save_people_dir: Cartella dove salvare i file profilo ''' # Apre il browser per Facebook _scrape_logger.info('Creation of Facebook scraper') fb_scraper = fb_functions.fb_scraper(_fb_logger) fb_scraper.init_scraper(use_proxy=False) if not fb_scraper.fb_login(password_manager.fb_email, password_manager.fb_password): print(colored('[FACEBOOK]', 'blue', 'on_white') + ' Unable to login to Facebook') _scrape_logger.error('Unable to login to Facebook') fb_scraper.terminate() # Crea l'istanza per Instagram _scrape_logger.info('Creation of Instagram scraper') ig_scraper = ig_functions.ig_scraper(_ig_logger) if not ig_scraper.login_anonymously(): print(colored('[INSTAGRAM]', 'magenta') + ' Unable to login to Instagram') _scrape_logger.error('Unable to login to Instagram') ig_scraper.terminate() # Inizia lo scraping _scrape_logger.info('Search for Instagram and Facebook users') for p in tqdm(people, 'Search for Instagram and Facebook users'): # Ottiene il percorso di salvataggio del file save_path = os.path.join(save_people_dir, '{}.person'.format(p.id)) # Se l'utente ha scelto di terminare l'applicazione # vengono chiuse le istanze degli scraper if _terminate_program: fb_scraper.terminate() ig_scraper.terminate() _end_program() _scrape_logger.debug('Search user FB/IG profiles with profile ID {}, name {} {}' .format(p.id, p.first_name, p.last_name)) # Verifica che il profilo Facebook non sia stato bloccato if fb_scraper.is_blocked: fb_scraper.terminate() tqdm.write(colored('[Facebook]', 'blue', 'on_white') + ' Facebook profile has been blocked, now proceeding with only Instagram...') # Verifica se già esiste un profilo Facebook if not len(p.get_profiles('Facebook')) > 0 and fb_scraper.is_logged: # Ricerca del profilo Instagram result = p.find_facebook_profile(fb_scraper, 'italia') if result > 0: tqdm.write(colored('[Facebook]', 'blue', 'on_white') + generic.only_ASCII(' Identified compatible Facebook profile for {} {} ({} references)' .format(p.first_name, p.last_name, result))) # Salva i risultati pickle.dump(p, open(save_path, 'wb'), protocol=pickle.HIGHEST_PROTOCOL) database.set_person_checked(_db_path, p.id, 'Facebook') # Verifica se già esiste un profilo Instagram if not len(p.get_profiles('Instagram')) > 0 and ig_scraper.is_initialized: # Ricerca del profilo Instagram result = p.find_instagram_profile(ig_scraper) if result > 0: tqdm.write(colored('[Instagram]', 'magenta') + generic.only_ASCII(' Identified compatible Instagram profile for {} {} ({} references)' .format(p.first_name, p.last_name, result))) # Salva i risultati pickle.dump(p, open(save_path, 'wb'), protocol=pickle.HIGHEST_PROTOCOL) database.set_person_checked(_db_path, p.id, 'Instagram') # Chiude il browser Facebook _scrape_logger.info('Facebook WebDriver instance termination') fb_scraper.terminate() # Chiude il client Instagram _scrape_logger.info('Instagram client termination') ig_scraper.terminate()