Merge pull request #3 from j4rj4r/fix-use-all-categories

Fix - Use all categories
This commit is contained in:
Jarjar 2023-02-07 22:21:18 +01:00 committed by GitHub
commit f8192e0011
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 52 additions and 39 deletions

View File

@ -1,7 +1,10 @@
./data/logs/*.logs
./data/data.db
./data/profiles/prof_*
.vscode
.gitignore
.idea/
./__pycache__/
./GlobalExambBot/__pycache__/
./GlobalExambBot/__pycache__/
.git
*.md

View File

@ -21,11 +21,11 @@ class Sheets:
WebDriverWait(self.driver, 15).until(ec.visibility_of_element_located((By.XPATH, self.pagecard_xpath)))
page_cards = self.driver.find_elements(by=By.XPATH, value=self.pagecard_xpath)
card_list = []
for card in page_cards :
for card in page_cards :
if not self.manageSheets.link_exist(card.get_attribute('href')):
card_list.append(card)
return card_list
def watch(self, Sheets_el):
self.actions.move_to_element(Sheets_el).click(Sheets_el).perform()
WebDriverWait(self.driver, 15).until(ec.visibility_of_element_located((By.XPATH, self.Sheetscard_xpath)))

View File

@ -1,5 +1,6 @@
import logging
import os
import sys
from GlobalExamBot.helpers import TypeInField, element_exists, wait_between
from GlobalExamBot.Sheets import Sheets
@ -11,6 +12,7 @@ from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
class Bot:
def __init__(self, driver, action, configuration):
self.driver = driver
self.actions = action
@ -18,7 +20,7 @@ class Bot:
self.email_xpath = '//input[@name="email"]'
self.password_xpath = '//input[@name="password"]'
self.index = 0
self.scrollcount = 0
self.catindex = 0
self.categories = ['https://exam.global-exam.com/library/study-sheets/categories/grammar',
'https://exam.global-exam.com/library/study-sheets/categories/language-functions',
'https://exam.global-exam.com/library/study-sheets/categories/vocabulary']
@ -33,7 +35,7 @@ class Bot:
password_el.send_keys(Keys.RETURN)
def run(self):
profile = f'prof_{self.configuration.username}'
if not os.path.exists(f'./Profiles/{profile}'):
@ -49,20 +51,17 @@ class Bot:
Sheets_action = Sheets(self.driver, self.actions, self.configuration)
while True:
self.driver.get('https://exam.global-exam.com/library/study-sheets/categories/grammar')
self.driver.get(self.categories[self.catindex])
Sheets_list = Sheets_action.search()
if Sheets_list :
logging.info(f'Sheets n°{ self.index }')
Sheets_action.watch(Sheets_list[0])
self.index +=1
self.scrollcount = 0
wait_between(3,10)
else:
logging.info('All visible Sheets have already been read. Need to scroll down ...')
self.driver.execute_script(f"window.scrollTo(0, document.body.scrollHeight)")
self.scrollcount += 1
wait_between(5,15)
if self.scrollcount > 10:
logging.info('End of page or network error.')
self.scrollcount = 0
logging.info(self.driver.get_log('browser'))
if self.catindex != len(self.categories) - 1 :
logging.info('All visible Sheets have already been read. Use of the next category.')
self.catindex += 1
else:
logging.info('No category available.')
sys.exit(1)

View File

@ -1,4 +1,4 @@
def init():
global VERSION, APP_NAME
APP_NAME = 'GlobalExamBot'
VERSION = '1.0.0'
VERSION = '1.0.0'

View File

@ -1,6 +1,9 @@
import sqlite3
class Database:
"""
Database management
"""
def __init__(self, database_link='./data/data.db'):
"""
Database constructor
@ -18,7 +21,7 @@ class Database:
c.execute('''INSERT INTO sheet_links (link) VALUES (:link);''', (link,))
c.close()
connection.commit()
def link_exist(self, link):
"""
Returns true if the link exists in the database.
@ -45,4 +48,4 @@ def create_table_sheets():
c.execute('''CREATE TABLE IF NOT EXISTS sheet_links
(id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, link text);''')
c.close()
connection.commit()
connection.commit()

View File

@ -3,6 +3,9 @@ from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.chrome.options import Options
class Driver:
"""
Browser management
"""
def __init__(self, profile):
self.profile = profile
self.chrome_options = None
@ -10,6 +13,9 @@ class Driver:
self.action = None
def setup(self, log_path='./data/logs/', headless=True):
"""
Browser configuration
"""
self.chrome_options = Options()
# Anti bot detection
@ -22,7 +28,7 @@ class Driver:
# Maximize Browser
self.chrome_options.add_argument('--start-maximized')
# Headless Mode
if headless:
self.chrome_options.add_argument('--headless')
@ -44,7 +50,6 @@ class Driver:
self.chrome_options.add_argument("--disable-low-res-tiling")
self.chrome_options.add_argument("--log-level=3")
self.chrome_options.add_argument("--silent")
# Disable save password
prefs = {'credentials_enable_service': False,
@ -54,12 +59,12 @@ class Driver:
# Set profile
self.chrome_options.add_argument(f'user-data-dir=./data/profiles/{self.profile}')
self.driver = webdriver.Chrome(f'./ChromeDriver/chromedriver',options=self.chrome_options, service_args=[f'--log-path={log_path}ChromeDriver.log'])
self.driver = webdriver.Chrome('./ChromeDriver/chromedriver',options=self.chrome_options, service_args=[f'--log-path={log_path}ChromeDriver.log'])
self.action = ActionChains(self.driver)
return self.driver, self.action
def get_driver(self):
return self.driver
def get_action(self):
return self.action
return self.action

View File

@ -38,7 +38,7 @@ class Helpers:
def load_configuration(self):
"""
this method allows you to load arguments.
:return: args
:return: args
"""
header()
# Load all configuration variables
@ -50,10 +50,13 @@ class Helpers:
return args
def logging_configuration(self, logging_level=logging.INFO, filename='data/logs/bot_globalexam.log'):
"""
Log configuration
"""
logging.basicConfig(filename=filename,
level=logging_level,
format='%(asctime)s - %(levelname)s - %(message)s')
root_logger = logging.getLogger()
root_logger.setLevel(logging_level)
@ -74,26 +77,26 @@ def header():
logging.info('==\t version : ' + const.VERSION + ' \t==')
logging.info('==\t=============================================================\t==')
def wait_between( min, max):
def wait_between( minimum, maximum):
"""
Wait random time in second beetween min and max seconds, to have an not linear behavior and be more human.
Wait random time in second beetween min and max seconds,
to have an not linear behavior and be more human.
"""
rand=uniform(min, max)
rand=uniform(minimum, maximum)
sleep(rand)
def TypeInField(element, xpath, myValue):
def TypeInField(element, xpath, value):
"""Type in a field"""
val = myValue
elem = element.find_element(by=By.XPATH, value=xpath)
for i in range(len(val)):
elem.send_keys(val[i])
for ele in enumerate(value):
elem.send_keys(ele[1])
wait_between(0.2, 0.4)
wait_between(0.4, 0.7)
def element_exists(xpath, element, by=By.XPATH):
"""
Check if an element exist
:return: Boolean
"""
try:
@ -101,4 +104,4 @@ def element_exists(xpath, element, by=By.XPATH):
element.find_element(by=by, value=xpath)
except:
return False
return True
return True

View File

@ -8,14 +8,14 @@ from GlobalExamBot.database import create_table_sheets
from GlobalExamBot.driver import Driver
from GlobalExamBot.bot import Bot
def main():
try:
helpers = Helpers()
# Configuration of the logging library
helpers.logging_configuration()
# Load all configuration variables
config = helpers.load_configuration()
@ -24,7 +24,7 @@ def main():
create_table_sheets()
profile = f'prof_{config.username}'
logging.info(f'Username : {config.username}')
# Initialize driver and actions
@ -46,4 +46,4 @@ def main():
sys.exit(1)
if __name__ == "__main__":
main()
main()