def follow_person_by_name(name): driver = get_driver() logger.info('Following {}'.format(name)) driver.get('https://www.instagram.com/{}'.format(name)) follow_button = _get_follow_button() if follow_button is None: save_debug(message='Could not find follow button') return constants.CANNOT_FOLLOW if follow_button.text == 'Following': logger.info('Already followed') return constants.ALREADY_FOLLOWING follow_button.click() try: wait_for_element('//*[contains(text(), \'Following\')]', selector_type=By.XPATH, from_element=driver.find_element_by_css_selector( 'header > section > div:nth-child(1)')) logger.info('Followed!') return constants.NEW_FOLLOWING except TimeoutException as e: logger.error('Could not follow') return constants.CANNOT_FOLLOW
def get_current_following_number(): driver = get_driver() profile_link = wait_for_element( 'span[aria-label=Profile]').find_element_by_xpath('..').get_attribute( 'href') driver.get(profile_link) return int( wait_for_element( 'header > section > ul > li:nth-child(3) > a > span').text)
def _fetch(): current_nof_people_in_page = len( driver.find_elements_by_css_selector(PROFILES_SELECTOR)) for x in range(0, 50): new_nof_people_in_page = len( driver.find_elements_by_css_selector(PROFILES_SELECTOR)) if new_nof_people_in_page == current_nof_people_in_page: time.sleep(0.2) else: current_nof_people_in_page = new_nof_people_in_page break time.sleep(0.5) elements = driver.find_elements_by_css_selector(PROFILES_SELECTOR) for el in elements: try: el.location_once_scrolled_into_view el.click() except (StaleElementReferenceException, WebDriverException): logger.warning('Could not click profile') break try: name = wait_for_element( 'article > header a[title]').get_attribute('title') except TimeoutException as e: logger.warning('Error getting name after profile click') continue logger.info('Found {}'.format(name)) names.append(name) driver.find_element_by_css_selector( 'body > div > div[role=dialog] > button').click()
def login(username, password): driver = get_driver() driver.get('https://www.instagram.com/accounts/login/') wait_for_element('input[name=username]') username_input = driver.find_element_by_name('username') password_input = driver.find_element_by_name('password') username_input.send_keys(username) password_input.send_keys(password) login_button = driver.find_element_by_css_selector('button[type=submit]') login_button.click() try: wait_for_element('//*[contains(text(), \'Send Security Code\')]', selector_type=By.XPATH) send_security_code_button = find_element_by_text('Send Security Code') prev_code = get_gettt_code() send_security_code_button.click() if prev_code is None: security_code = input('Check you email for security code: ') else: logger.debug('Getting security code using Gettt') iterations = 0 while True: new_code = get_gettt_code() if new_code != prev_code: security_code = new_code logger.info('Security code: {}'.format(security_code)) break else: if iterations == 60: logger.warning( 'Could not retrieve security code using Gettt, please type it manually' ) security_code = input( 'Check you email for security code: ') time.sleep(5) iterations += 1 security_code_input = driver.find_element_by_name('security_code') security_code_input.send_keys(security_code) submit_button = driver.find_element_by_css_selector('form button') submit_button.click() except TimeoutException as e: pass try: wait_for_element('span[aria-label=Profile]') except TimeoutException as e: raise LoginFailedException('Could not log in correctly')
def unfollow_everyone(last_following_number=None, nof_times_same_following=0, profile_link=None): driver = get_driver() profile_link = wait_for_element( 'span[aria-label=Profile]').find_element_by_xpath('..').get_attribute( 'href') driver.get(profile_link) wait_for_element( 'section > main > div > header > section > ul > li:nth-child(3) > a' ).click() wait_for_element('div[role="dialog"] ul li button') first_person = driver.find_elements_by_css_selector( 'div[role="dialog"] ul li button')[0] first_person.location_once_scrolled_into_view following_classes = first_person.get_attribute('class').split(' ') first_person.click() wait_for_element( 'div[role=presentation] > div[role=dialog] > div > div > button:nth-child(1)' ).click() first_person = driver.find_elements_by_css_selector( 'div[role="dialog"] ul li button')[0] while True: not_following_classes = first_person.get_attribute('class').split(' ') following_class = list( set(following_classes).difference(set(not_following_classes))) if len(following_class) == 0: time.sleep(0.5) continue following_class = following_class[0] break following_people = driver.find_elements_by_css_selector( 'div[role="dialog"] ul li button.{}'.format(following_class)) for person in following_people: try: person.location_once_scrolled_into_view person.click() time.sleep(5) wait_for_element( 'div[role=presentation] > div[role=dialog] > div > div > button:nth-child(1)' ).click() time.sleep(5) except (StaleElementReferenceException, TimeoutException): break while True: if len(person.find_elements_by_css_selector('svg')) > 0: time.sleep(0.5) else: logger.info('Person unfollowed') break driver.get(profile_link) current_following_number = int( wait_for_element( 'section > main > div > header > section > ul > li:nth-child(3) > a > span' ).text) if current_following_number > 0: logger.info( 'Current following number: {}'.format(current_following_number)) if current_following_number == last_following_number: logger.info('Throttling...') time.sleep(10 * nof_times_same_following) nof_times_same_following += 1 unfollow_everyone(last_following_number=current_following_number, nof_times_same_following=nof_times_same_following, profile_link=profile_link)
def get_suggested_people(nof_scrolls=0): def _fetch(): current_nof_people_in_page = len( driver.find_elements_by_css_selector(PROFILES_SELECTOR)) for x in range(0, 50): new_nof_people_in_page = len( driver.find_elements_by_css_selector(PROFILES_SELECTOR)) if new_nof_people_in_page == current_nof_people_in_page: time.sleep(0.2) else: current_nof_people_in_page = new_nof_people_in_page break time.sleep(0.5) elements = driver.find_elements_by_css_selector(PROFILES_SELECTOR) for el in elements: try: el.location_once_scrolled_into_view el.click() except (StaleElementReferenceException, WebDriverException): logger.warning('Could not click profile') break try: name = wait_for_element( 'article > header a[title]').get_attribute('title') except TimeoutException as e: logger.warning('Error getting name after profile click') continue logger.info('Found {}'.format(name)) names.append(name) driver.find_element_by_css_selector( 'body > div > div[role=dialog] > button').click() PROFILES_SELECTOR = 'article > div > div > div > div' retries = 10 driver = get_driver() driver.get('https://www.instagram.com/explore/') logger.info('Exploring...') for x in range(0, retries): try: wait_for_element('article') # This page fails sometimes break except TimeoutException as e: if x + 1 == retries: raise UnestableScrapperException( 'Suggested page failed to load', constants.ERROR_TIMEOUT_SUGGESTED) logger.warning('Page failed to load, reloading ({}/{})'.format( x + 1, retries)) time.sleep(2 * x) return get_suggested_people(nof_scrolls) names = [] _fetch() for x in range(0, nof_scrolls): scroll_to_bottom() _fetch() return list(set(names))