-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstahelpers.py
164 lines (139 loc) · 6.77 KB
/
instahelpers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import time
import re
import logging
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
NEWSFEED_STOP_CONTINUOUS_ALREADY_LIKED = 20
XPATH_LOGIN_INPUT = "//input[@name='username']"
XPATH_PASSWORD_INPUT = "//input[@name='password']"
XPATH_LOGIN_BUTTON = "//button[@type='submit']"
XPATH_TURN_ON_NOTIFICATIONS_TEXT = "//*[contains(text(),\"Turn on Notifications\")]"
XPATH_NOT_NOW_TEXT = "//*[contains(text(),\"Not Now\")]"
class InstaDriver:
def __init__(self, is_headless, login, password):
logging.info("Initializing InstaDriver for login={0}".format(login))
self.login = login
self.password = password
userdatadir = "likebot_" + login
chrome_options = webdriver.ChromeOptions()
chrome_arguments = ["--disable-extensions", "--no-default-browser-check",
"--disable-sync", "--user-data-dir=" + userdatadir, "--disk-cache-size=102400"]
chrome_arguments.append('--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"')
if is_headless:
chrome_arguments.append("--headless")
chrome_arguments.append("--disable-gpu")
chrome_arguments.append("--window-size=1280,1280")
chrome_arguments.append("--no-sandbox")
chrome_arguments.append("--disable-dev-shm-usage")
for a in chrome_arguments:
chrome_options.add_argument(a)
self.driver = webdriver.Chrome(options=chrome_options)
def do_sleep(self, tick):
time.sleep(tick * 2)
def go_url(self, url):
logging.info("Goto url: {0}".format(url))
self.driver.get(url)
self.do_sleep(1)
def do_click_delay(self, element, tick):
webdriver.ActionChains(self.driver).move_to_element(element).click(element).perform()
self.do_sleep(tick)
def do_click(self, element):
self.do_click_delay(element, 1)
def check_already_logged_user(self):
try:
self.driver.find_element_by_xpath('//a[@href="/{0}/"]'.format(self.login))
logging.info("User is already logged")
return True
except NoSuchElementException:
logging.info("User is not logged")
return False
def do_login(self):
logging.info("Doing login for user: {0}".format(self.login))
self.go_url("https://instagram.com/accounts/login")
login_input = self.driver.find_element_by_xpath(XPATH_LOGIN_INPUT)
login_input.send_keys(self.login)
password_input = self.driver.find_element_by_xpath(XPATH_PASSWORD_INPUT)
password_input.send_keys(self.password)
login_button = self.driver.find_element_by_xpath(XPATH_LOGIN_BUTTON)
self.do_click_delay(login_button, 3)
url = self.driver.current_url
logging.info("Url after login: {0}".format(url))
if url.find("#reactivated") > 0:
self.do_click(self.driver.find_element_by_xpath(XPATH_NOT_NOW_TEXT))
return True
if url.endswith("instagram.com") or url.endswith("instagram.com/"):
return True
logging.error("Login has been failed".format(url))
return False
def suppress_notifications(self):
try:
self.driver.find_element_by_xpath(XPATH_TURN_ON_NOTIFICATIONS_TEXT)
self.do_click(self.driver.find_element_by_xpath(XPATH_NOT_NOW_TEXT))
logging.info("Notifications have been suppressed")
except NoSuchElementException:
pass
def find_article_url(self, article):
article_url = ""
ahrefs = article.find_elements_by_xpath("div[2]/..//a")
for ahref in ahrefs:
attr = ahref.get_attribute("href")
if re.search("liked_by", attr) is not None:
continue
x = re.search("https://www.instagram.com/p/.{9,50}/$", attr)
if x is not None:
article_url = attr
break
return article_url
def like_newsfeed_article(self, article, article_url, author):
try:
unlike = article.find_element_by_xpath('div[2]/section/span/..//*[@aria-label="Unlike"]')
return False
except NoSuchElementException:
pass
elements = article.find_elements_by_xpath('div[2]/section/span/..//*[@aria-label="Like"]')
for ele in elements:
self.do_click_delay(ele, 3)
logging.info("+++ Liked newsfeed article: {0} by {1}".format(article_url, author))
break
return True
def do_like_newsfeed(self, likes_max):
logging.info("Doing article newsfeed for login: {0}".format(self.login))
likes_count = 0
already_liked_continuous = 0
articles_discovered = 0
visited = {}
while True:
articles = self.driver.find_elements_by_xpath("//article")
likes_current_articles = 0
for article in articles:
article_url = self.find_article_url(article)
if article_url == "":
logging.error("Unable for find article_url")
break
# if article is already visited, skip it
if visited.get(article_url) is None:
author = article.find_element_by_xpath('header/.//a').get_attribute("href").replace("https://www.instagram.com/","").replace("/","")
logging.info("Found newsfeed article: {0} by {1}".format(article_url, author))
visited[article_url] = 1
self.driver.execute_script("arguments[0].scrollIntoView(true);", article)
self.do_sleep(1)
articles_discovered += 1
if self.like_newsfeed_article(article, article_url, author) is True:
already_liked_continuous = 0
likes_count += 1
likes_current_articles += 1
else:
already_liked_continuous += 1
if likes_count >= likes_max:
break
if already_liked_continuous >= NEWSFEED_STOP_CONTINUOUS_ALREADY_LIKED:
logging.info("Stopping because continuous already liked is exceeded")
break
if likes_current_articles == 0 and articles_discovered >= NEWSFEED_STOP_CONTINUOUS_ALREADY_LIKED:
logging.info("Break because likes_current_articles is zero")
break
if already_liked_continuous >= NEWSFEED_STOP_CONTINUOUS_ALREADY_LIKED:
logging.info("Stopping because continuous already liked is exceeded")
break
logging.info("Breaking... Total likes made: {0}".format(likes_count))
return likes_count