diff --git a/config.json b/config.json index 0b432a4..f1bafb0 100644 --- a/config.json +++ b/config.json @@ -3,5 +3,5 @@ "password" : "your_password", "keywords" : "your_keywords", "location" : "your_location", - "driver_path" : "your_path_to_webdriver" + "optional_driver_path" : "" } \ No newline at end of file diff --git a/main.py b/main.py index 0232efa..adbb053 100644 --- a/main.py +++ b/main.py @@ -18,7 +18,20 @@ def __init__(self, data): self.password = data['password'] self.keywords = data['keywords'] self.location = data['location'] - self.driver = webdriver.Chrome(data['driver_path']) + try: + if data['optional_driver_path'] != '': + # user driver path is defined + self.driver = webdriver.Chrome(data['optional_driver_path']) + else: + # use new way of getting chrome webdriver user did not set driver path + options = webdriver.ChromeOptions() + self.driver = webdriver.Chrome(options=options) + except: + # Driver issue, ending program + print("Chrome driver issue. Try updating chrome to Version 116 or higher") + print('Ensure driver_path is set correctly in config.json or set driver_config to "" ') + print('Exiting...') + exit() def login_linkedin(self): """This function logs into your personal LinkedIn profile""" @@ -27,10 +40,10 @@ def login_linkedin(self): self.driver.get("https://www.linkedin.com/login") # introduce email and password and hit enter - login_email = self.driver.find_element_by_name('session_key') + login_email = self.driver.find_element(By.NAME, 'session_key') login_email.clear() login_email.send_keys(self.email) - login_pass = self.driver.find_element_by_name('session_password') + login_pass = self.driver.find_element(By.NAME, 'session_password') login_pass.clear() login_pass.send_keys(self.password) login_pass.send_keys(Keys.RETURN) @@ -39,14 +52,14 @@ def job_search(self): """This function goes to the 'Jobs' section a looks for all the jobs that matches the keywords and location""" # go to Jobs - jobs_link = self.driver.find_element_by_link_text('Jobs') + jobs_link = self.driver.find_element(By.LINK_TEXT, 'Jobs') jobs_link.click() # search based on keywords and location and hit enter - search_keywords = self.driver.find_element_by_css_selector(".jobs-search-box__text-input[aria-label='Search jobs']") + search_keywords = self.driver.find_element(By.CSS_SELECTOR, ".jobs-search-box__text-input[aria-label='Search jobs']") search_keywords.clear() search_keywords.send_keys(self.keywords) - search_location = self.driver.find_element_by_css_selector(".jobs-search-box__text-input[aria-label='Search location']") + search_location = self.driver.find_element(By.CSS_SELECTOR, ".jobs-search-box__text-input[aria-label='Search location']") search_location.clear() search_location.send_keys(self.location) search_location.send_keys(Keys.RETURN) @@ -55,33 +68,33 @@ def filter(self): """This function filters all the job results by 'Easy Apply'""" # select all filters, click on Easy Apply and apply the filter - all_filters_button = self.driver.find_element_by_xpath("//button[@data-control-name='all_filters']") + all_filters_button = self.driver.find_element(By.XPATH, "//button[@data-control-name='all_filters']") all_filters_button.click() time.sleep(1) - easy_apply_button = self.driver.find_element_by_xpath("//label[@for='f_LF-f_AL']") + easy_apply_button = self.driver.find_element(By.XPATH, "//label[@for='f_LF-f_AL']") easy_apply_button.click() time.sleep(1) - apply_filter_button = self.driver.find_element_by_xpath("//button[@data-control-name='all_filters_apply']") + apply_filter_button = self.driver.find_element(By.XPATH, "//button[@data-control-name='all_filters_apply']") apply_filter_button.click() def find_offers(self): """This function finds all the offers through all the pages result of the search and filter""" # find the total amount of results (if the results are above 24-more than one page-, we will scroll trhough all available pages) - total_results = self.driver.find_element_by_class_name("display-flex.t-12.t-black--light.t-normal") + total_results = self.driver.find_element(By.CLASS_NAME, "display-flex.t-12.t-black--light.t-normal") total_results_int = int(total_results.text.split(' ',1)[0].replace(",","")) print(total_results_int) time.sleep(2) # get results for the first page current_page = self.driver.current_url - results = self.driver.find_elements_by_class_name("occludable-update.artdeco-list__item--offset-4.artdeco-list__item.p0.ember-view") + results = self.driver.find_elements(By.CLASS_NAME, "occludable-update.artdeco-list__item--offset-4.artdeco-list__item.p0.ember-view") # for each job add, submits application if no questions asked for result in results: hover = ActionChains(self.driver).move_to_element(result) hover.perform() - titles = result.find_elements_by_class_name('job-card-search__title.artdeco-entity-lockup__title.ember-view') + titles = result.find_elements(By.CLASS_NAME, 'job-card-search__title.artdeco-entity-lockup__title.ember-view') for title in titles: self.submit_apply(title) @@ -90,10 +103,10 @@ def find_offers(self): time.sleep(2) # find the last page and construct url of each page based on the total amount of pages - find_pages = self.driver.find_elements_by_class_name("artdeco-pagination__indicator.artdeco-pagination__indicator--number") + find_pages = self.driver.find_elements(By.CLASS_NAME, "artdeco-pagination__indicator.artdeco-pagination__indicator--number") total_pages = find_pages[len(find_pages)-1].text total_pages_int = int(re.sub(r"[^\d.]", "", total_pages)) - get_last_page = self.driver.find_element_by_xpath("//button[@aria-label='Page "+str(total_pages_int)+"']") + get_last_page = self.driver.find_element(By.XPATH, "//button[@aria-label='Page "+str(total_pages_int)+"']") get_last_page.send_keys(Keys.RETURN) time.sleep(2) last_page = self.driver.current_url @@ -103,11 +116,11 @@ def find_offers(self): for page_number in range(25,total_jobs+25,25): self.driver.get(current_page+'&start='+str(page_number)) time.sleep(2) - results_ext = self.driver.find_elements_by_class_name("occludable-update.artdeco-list__item--offset-4.artdeco-list__item.p0.ember-view") + results_ext = self.driver.find_elements(By.CLASS_NAME, "occludable-update.artdeco-list__item--offset-4.artdeco-list__item.p0.ember-view") for result_ext in results_ext: hover_ext = ActionChains(self.driver).move_to_element(result_ext) hover_ext.perform() - titles_ext = result_ext.find_elements_by_class_name('job-card-search__title.artdeco-entity-lockup__title.ember-view') + titles_ext = result_ext.find_elements(By.CLASS_NAME, 'job-card-search__title.artdeco-entity-lockup__title.ember-view') for title_ext in titles_ext: self.submit_apply(title_ext) else: @@ -122,7 +135,7 @@ def submit_apply(self,job_add): # click on the easy apply button, skip if already applied to the position try: - in_apply = self.driver.find_element_by_xpath("//button[@data-control-name='jobdetails_topcard_inapply']") + in_apply = self.driver.find_element(By.XPATH, "//button[@data-control-name='jobdetails_topcard_inapply']") in_apply.click() except NoSuchElementException: print('You already applied to this job, go to next...') @@ -131,17 +144,17 @@ def submit_apply(self,job_add): # try to submit if submit application is available... try: - submit = self.driver.find_element_by_xpath("//button[@data-control-name='submit_unify']") + submit = self.driver.find_element(By.XPATH, "//button[@data-control-name='submit_unify']") submit.send_keys(Keys.RETURN) # ... if not available, discard application and go to next except NoSuchElementException: print('Not direct application, going to next...') try: - discard = self.driver.find_element_by_xpath("//button[@data-test-modal-close-btn]") + discard = self.driver.find_element(By.XPATH, "//button[@data-test-modal-close-btn]") discard.send_keys(Keys.RETURN) time.sleep(1) - discard_confirm = self.driver.find_element_by_xpath("//button[@data-test-dialog-primary-btn]") + discard_confirm = self.driver.find_element(By.XPATH, "//button[@data-test-dialog-primary-btn]") discard_confirm.send_keys(Keys.RETURN) time.sleep(1) except NoSuchElementException: