forked from steve-codes/selenium-web-bot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
173 lines (144 loc) · 7.07 KB
/
main.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
165
166
167
168
169
170
171
172
173
import configparser
import pandas as pd
import time
import os.path
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from fake_useragent import UserAgent
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.chrome.options import Options
import keyring
import pickle
import re
import undetected_chromedriver as uc
import random
def main():
idRegex = r'id="(.*?)"'
#setup the config parser (where the html identifiers are stored)
config = configparser.ConfigParser()
config.read('settings.ini')
#setup the chrome webdriver
driver = setupDriver()
driver.get('https://www.investopedia.com/simulator/')
#load previously saved cookies
if (os.path.isfile('cookies.pkl')):
cookies = pickle.load(open("cookies.pkl", "rb"))
for cookie in cookies:
driver.add_cookie(cookie)
#login to the website
login(driver, config)
#click the trade button on website and halt
waitToLoad(driver, By.XPATH, config.get('tradePath', 'tradeB'))
driver.find_element(By.XPATH, config.get('tradePath', 'tradeB')).click()
haltStep()
#read the excel file as a dataframe
df = pd.read_excel(r'orders.xlsx', sheet_name='Sheet1')
#for ever row in the orders.xlsx file we will fill it out on the website
for index, row in df.iterrows():
#enter stock ticker into search bar
waitToLoad(driver, By.CLASS_NAME, config.get('tradePath', 'dropDown'))
dropdownSelect = driver.find_elements(By.CLASS_NAME, config.get('tradePath', 'dropDown'))
#enter the selected stock from the file into the search box and halt
stockInput = getIDs(driver, config, idRegex, False, element=dropdownSelect[0])
waitToLoad(driver, By.ID, stockInput[0])
driver.find_element(By.ID, stockInput[0]).send_keys(row.get('Stock'))
haltStep()
#click the corresponding stock in the drop-down menu and halt
tickerIDs = getIDs(driver, config, idRegex, True, pathHeading='tradePath', pathItem='dropDownList')
enterDropDownVal(driver, tickerIDs, row.get('Stock'))
haltStep()
#click the action dropdown and fill it out and then halt
searchAndClickDropDown(driver, config, idRegex, 'tradePath', dropdownSelect[1], 'dropDownList', row.get('Action'))
haltStep()
#fill in the quantity and halt
quantityInput = getIDs(driver, config, idRegex, True, pathHeading='tradePath', pathItem='quantity')
waitToLoad(driver, By.ID, quantityInput[0])
driver.find_element(By.ID, quantityInput[0]).send_keys(row.get('Quantity'))
haltStep()
#fill in the order type and halt
searchAndClickDropDown(driver, config, idRegex, 'tradePath', dropdownSelect[2], 'dropDownList', row.get('Order Type'))
haltStep()
#fill in the duration and halt
searchAndClickDropDown(driver, config, idRegex, 'tradePath', dropdownSelect[3], 'dropDownList', row.get('Duration'))
haltStep()
#click the preview order button and halt
waitToLoad(driver, By.CLASS_NAME, config.get('tradePath', 'previewOrderB'))
driver.find_element(By.CLASS_NAME, config.get('tradePath', 'previewOrderB')).click()
haltStep()
#click the confirm order button (it uses the same css class as the preview button) and halt
waitToLoad(driver, By.CLASS_NAME, config.get('tradePath', 'previewOrderB')[1])
driver.find_elements(By.CLASS_NAME, config.get('tradePath', 'previewOrderB'))[1].click()
haltStep()
#click the button to go back to the order screen and halt
waitToLoad(driver, By.LINK_TEXT, "click here")
driver.find_element(By.LINK_TEXT, "click here").click()
haltStep()
#dump the cookies back into the file
pickle.dump(driver.get_cookies(), open('cookies.pkl', 'wb'))
#driver quits
driver.quit()
#setup the driver
def setupDriver():
options = Options()
options.add_argument(f'user-agent={UserAgent().random}')
options.add_argument("--start-maximized")
#fill in this line if you want to use your own user data
#options.add_argument("user-data-dir=")
driver = uc.Chrome(options=options, executable_path='chromedriver.exe')
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
driver.implicitly_wait(10)
return driver
#logins the user to the website
def login(driver, config):
driver.find_element(By.XPATH, config.get('loginPath', 'loginLink')).click()
haltStep()
driver.find_element(By.XPATH, config.get('loginPath', 'userName')).send_keys(keyring.get_password("investopedia", 'userLogin'))
haltStep()
driver.find_element(By.XPATH, config.get('loginPath', 'password')).send_keys(keyring.get_password('investopedia', 'userName'))
haltStep()
driver.find_element(By.XPATH, config.get('loginPath', 'loginB')).click()
haltStep()
#gets IDs from the innerHTML of a parent HTML section
def getIDs(driver, config, regexInput, searchClass, pathHeading=None, pathItem=None, element=None):
innerHTML = ''
if searchClass == True:
#find the HTML code for the dynamic listbox (for selecting from the listbox)
waitToLoad(driver, By.CLASS_NAME, config.get(pathHeading, pathItem))
elements = driver.find_elements(By.CLASS_NAME, config.get(pathHeading, pathItem))
innerHTML = elements[len(elements)-1].get_attribute('innerHTML')
else:
innerHTML = element.get_attribute('innerHTML')
#find the id of the first element in the listbox and grab it
ids = re.findall(regexInput, innerHTML)
return ids
#helper method for searchAndClickDropDown, will search all items in a drop down list
def enterDropDownVal(driver, ids, rowValue):
for actionID in ids:
#check to see if the stock from the file is listed in the list results
waitToLoad(driver, By.ID, actionID)
actionText = driver.find_element(By.ID, actionID).get_attribute('innerHTML')
actionValue = re.search(rowValue, actionText)
if (actionValue != None):
#confirm the stock is the same as the one in the file
if (actionValue.group() == rowValue):
waitToLoad(driver, By.ID, actionID)
driver.find_element(By.ID, actionID).click()
break
#clicks the dropdown to open and submits the option from the excel file
def searchAndClickDropDown(driver, config, idRegex, pathHeading, dropDownPath, dropDownList, rowVal):
dropDownPath.click()
ids = getIDs(driver, config, idRegex, True, pathHeading=pathHeading, pathItem=dropDownList)
enterDropDownVal(driver, ids, rowVal)
#makes sure an element loads before clicking it
def waitToLoad(driver, byType, identifier):
try:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((byType, identifier)))
except:
TimeoutException
#randomly stops the script between 1-3 seconds (to avoid detection)
def haltStep():
int = random.randint(1, 3)
time.sleep(int)
if __name__ == "__main__":
main()