Created
June 21, 2024 22:09
-
-
Save SadSack963/25470daf6bc28677dec0e4b200ec9bbf to your computer and use it in GitHub Desktop.
Day 52 Instagram Follower Bot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from dotenv import load_dotenv | |
from selenium import webdriver, common | |
from selenium.webdriver.common.keys import Keys | |
from selenium.webdriver.chrome.options import Options | |
from selenium.webdriver.common.by import By | |
from time import sleep | |
import random | |
load_dotenv("D:/Python/EnvironmentVariables/.env") | |
USERNAME = os.getenv("Username_Instagram") | |
PASSWORD = os.getenv("Password_Instagram") | |
BASE_URL = "https://www.instagram.com/" | |
INTERESTING_ACCOUNT = "buzzfeedtasty" # "pythonclubb" | |
class InstaFollower: | |
def __init__(self): | |
options = Options() | |
options.add_experimental_option("detach", True) | |
# ========================================================================================== | |
# Use a Chrome profile to look more like a human :) | |
# Specify path to Chrome User Data Folder | |
options.add_argument(r'--user-data-dir=C:\Users\John\AppData\Local\Google\Chrome\User Data') | |
# This creates the new user I have called SeleniumProfile | |
options.add_argument('--profile-directory=SeleniumProfile') | |
# NOTE. Since we are using a profile, if the script crashes or is interrupted, then we remain logged in. | |
# When the script opens the URL again, we will still be logged in and at the page your were previously on. | |
# Make sure you log out before starting the script again to have a clean run! | |
# ========================================================================================== | |
self.driver = webdriver.Chrome(options=options) | |
self.xpath = "xpath_1" # Default XPATH used for the "Follow" buttons | |
def find_element(self, xpath, comment="", retries=1): | |
print(comment) | |
print(f"Finding {xpath}") | |
while retries: | |
retries -= 1 # Allows for slow page loading | |
try: | |
element = self.driver.find_element(by=By.XPATH, value=xpath) | |
print("Element found.") | |
return element | |
except common.exceptions.ElementNotInteractableException: | |
print("Element Not Interactable Exception") | |
except common.exceptions.NoSuchElementException: | |
print("No Such Element Exception") | |
finally: | |
sleep(1) | |
def login(self, url): | |
self.driver.get(url) | |
# Click modal button to allow essential cookies | |
# Only required the first time if you use a profile | |
element = self.find_element( | |
xpath='/html/body/div[2]/div/div/div[2]/div/div/div[1]/div/div[2]/div/div/div/div/div[2]/div/button[1]', | |
comment='Click modal button to allow essential cookies', | |
) | |
if element: | |
element.click() | |
# Input Username / Password and Login | |
element = self.find_element( | |
xpath='//*[@id="loginForm"]/div/div[1]/div/label/input', | |
comment='Input Username / Password and Login', | |
) | |
if element: | |
element.send_keys( | |
USERNAME + Keys.TAB + | |
PASSWORD + Keys.ENTER | |
) | |
# Click modal button again to allow essential cookies | |
# Only required the first time if you use a profile | |
# We must use the Full XPATH - the id changes every time the page is loaded | |
element = self.find_element( | |
xpath='/html/body/div[2]/div/div/div[3]/div/div/div[1]/div/div[2]/div/div/div/div/div[2]/div/div/div[3]/div[3]/div/div[1]/div', | |
comment='Click modal button again to allow essential cookies', | |
) | |
if element: | |
element.click() | |
# Don't save passwords | |
element = self.find_element( | |
xpath='//*[@id="react-root"]/section/main/div/div/div/div/button', | |
comment='Don\'t save passwords', | |
) | |
if element: | |
element.click() | |
# Dismiss Notifications | |
element = self.find_element( | |
# xpath='/html/body/div[4]/div/div/div/div[3]/button[2]' | |
xpath='/html/body/div[3]/div[1]/div/div[2]/div/div/div/div/div[2]/div/div/div[3]/button[2]', | |
comment='Dismiss Notifications', | |
) | |
if element: | |
element.click() | |
def find_followers(self, url): | |
self.driver.get(url) | |
sleep(5) # Wait for page to load | |
# Click on the "followers" text link to bring up the Followers Modal Pop-up | |
element = self.find_element( | |
xpath='/html/body/div[2]/div/div/div[2]/div/div/div[1]/div[2]/div/div[2]/section/main/div/header/section[3]/ul/li[2]/div/a', | |
comment='Followers Modal Pop-up', | |
) | |
if element: | |
element.click() | |
sleep(5) # Allow the modal to load | |
# Find the first "Follow" button in the modal area | |
xpath_1 = "/html/body/div[6]/div[2]/div/div/div[1]/div/div[2]/div/div/div/div/div[2]/div/div/div[2]/div[2]/div/div[1]/div/div/div/div[3]/div/button" | |
xpath_2 = "/html/body/div[6]/div[2]/div/div/div[1]/div/div[2]/div/div/div/div/div[2]/div/div/div[3]/div[1]/div/div[1]/div/div/div/div[3]/div/button" | |
element = self.find_element( | |
xpath=xpath_1, | |
comment='Find the first "Follow" button in the modal area - xpath_1', | |
) | |
self.xpath = "xpath_1" | |
if not element: | |
element = self.find_element( | |
xpath=xpath_2, | |
comment='Find the first "Follow" button in the modal area - xpath_2', | |
) | |
self.xpath = "xpath_2" | |
# Make the first few followers visible (scroll the modal contents down) | |
if element: | |
for _ in range(2): | |
element.send_keys(Keys.END) | |
sleep(2) # Allow the list to update | |
def follow(self): | |
count = 1 | |
while True: | |
if self.xpath == "xpath_1": | |
xpath = f"/html/body/div[6]/div[2]/div/div/div[1]/div/div[2]/div/div/div/div/div[2]/div/div/div[2]/div[2]/div/div[{count}]/div/div/div/div[3]/div/button" | |
else: | |
xpath = f"/html/body/div[6]/div[2]/div/div/div[1]/div/div[2]/div/div/div/div/div[2]/div/div/div[3]/div[1]/div/div[{count}]/div/div/div/div[3]/div/button" | |
element = self.find_element( | |
xpath=xpath, | |
comment=f'Find "Follow" button {count} in the modal area', | |
) | |
if not element: | |
break | |
if element.text == "Follow": | |
print(f"{count} followed") | |
# element.click() | |
sleep(random.randint(1, 4)) | |
count += 1 | |
# if count > 3: # <----- Limit actually following for testing purposes | |
# break | |
# TESTED Working - 20/06/2024 | |
# =========================== | |
insta_follower = InstaFollower() | |
if insta_follower.driver is None: | |
print('Cannot load webdriver.') | |
quit() | |
insta_follower.login(url=BASE_URL) | |
insta_follower.find_followers(url=BASE_URL + INTERESTING_ACCOUNT) | |
insta_follower.follow() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment