-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimplebrowser.py
184 lines (154 loc) · 6.24 KB
/
simplebrowser.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
174
175
176
177
178
179
180
181
182
183
184
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import TimeoutException
from selenium.common.exceptions import SessionNotCreatedException
from selenium.webdriver.chrome.options import Options
import selenium.webdriver.support.ui as ui
from selenium.webdriver.common.keys import Keys
import os
import time
import logging
import random
logger = logging.getLogger(__name__)
class SimpleBrowser:
@classmethod
def __create_chrome_driver(cls, width, height):
assert width
assert height
options = Options()
options.add_argument(f'--window-size={width},{height}')
# if width < 450:
# mobile_emulation = {
# 'deviceMetrics':
# { 'width': width, 'height': height, 'pixelRatio': 3.0}
# }
# options.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Chrome(options=options)
return driver
@classmethod
def __create_safari_driver(cls, width, height):
driver = webdriver.Safari()
driver.set_window_size(width, height)
return driver
@classmethod
def __create_driver(cls, browser, width, height):
assert browser in ['chrome', 'safari',
'firefox', None], 'unsupported browser'
driver = None
for i in range(0, 3):
try:
if browser == 'safari':
driver = SimpleBrowser.__create_safari_driver(
width=width, height=height)
if browser == 'chrome' or not browser:
driver = SimpleBrowser.__create_chrome_driver(
width=width, height=height)
except SessionNotCreatedException as e:
logger.exception('couldnt create session properly')
time.sleep(4)
if driver:
break
return driver
def __init__(self, browser, width, height):
self.browser = browser
self.driver = SimpleBrowser.__create_driver(
browser=browser, width=width, height=height)
assert self.driver, 'unable to initialize browser properly'
self.timeout = 5
self.wait = WebDriverWait(self.driver, self.timeout)
def close(self):
time.sleep(1)
driver = self.driver
self.driver = None
if driver:
driver.close()
time.sleep(2)
def __del__(self):
logger.debug('destructor called')
self.close()
def get(self, url):
return self.driver.get(url)
def checkbox_click(self, elem):
self.driver.execute_script("arguments[0].click();", elem)
def current_height(self):
return self.driver.execute_script("return document.body.scrollHeight")
def current_scroll_position(self):
return self.driver.execute_script("return window.pageYOffset")
def scroll_down_page(self, max_speed=300):
pos = self.current_scroll_position()
height = 1
while pos < height:
delta = random.randint(1, max_speed)
pos += delta
self.driver.execute_script(f'window.scrollTo(0, {pos});')
time.sleep(random.uniform(0.3, 1.0))
height = self.current_height()
def scroll_up_page(self, max_speed=300):
pos = self.current_scroll_position()
while pos > 0:
delta = random.randint(1, max_speed)
pos -= delta
if pos < 0:
pos = 0
self.driver.execute_script(f'window.scrollTo(0, {pos});')
time.sleep(random.uniform(0.3, 1.0))
def find(self, xpath, scroll=False):
l = self.wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
if scroll:
self.driver.execute_script("arguments[0].scrollIntoView(true);", l)
time.sleep(1)
l = self.wait.until(
EC.presence_of_element_located((By.XPATH, xpath)))
return l
def find_many(self, xpath):
m = self.wait.until(EC.presence_of_all_elements_located((By.XPATH, xpath)))
return m
def click(self, xpath, scroll=False):
l = self.find(xpath, scroll)
ltag = l.tag_name.lower() if l.tag_name else None
assert ltag in ['input', 'li', 'button', 'span',
'a', 'div', 'textarea'], 'xpath did not return proper element'
l = self.wait.until(
EC.element_to_be_clickable((By.XPATH, xpath)))
l.click()
return l
def input(self, xpath, keys, scroll=False):
l = self.find(xpath, scroll)
ltag = l.tag_name.lower() if l.tag_name else None
# logger.info('found element with tag %s', ltag)
assert ltag in ['input', 'li', 'button', 'span',
'a', 'div', 'textarea'], 'xpath did not return proper element'
l = self.wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
l.click()
for c in keys:
time.sleep(random.uniform(0.01, 0.04))
l.send_keys(c)
return l
def close_windows(self):
# close all windows except 0
while len(self.driver.window_handles) > 1:
w = self.driver.window_handles[-1]
self.driver.switch_to.window(w)
self.driver.close()
self.driver.switch_to.window(self.driver.window_handles[0])
def mark_divs(self):
for d in self.driver.find_elements_by_xpath("//div"):
self.driver.execute_script(
"arguments[0]['style']['border']='1px solid black';", d)
def get_width(self):
return self.driver.get_window_size()['width']
def get_height(self):
return self.driver.get_window_size()['height']
def is_desktop(self):
return self.get_width() >= 1024
def is_mobile(self):
return self.get_width() < 425
def is_tablet(self):
return self.get_width() >= 425 and self.get_width() < 1024
def get_current_url(self):
return self.driver.current_url
def set_window_size(self, width, height):
self.driver.set_window_size(width, height)