-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Automating job application on linkedin - bot
- Loading branch information
artur.sniegowski
committed
Sep 6, 2022
0 parents
commit b420a42
Showing
11 changed files
with
235 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Numerous always-ignore extensions | ||
*.diff | ||
*.err | ||
*.orig | ||
*.log | ||
*.rej | ||
*.swo | ||
*.swp | ||
*.vi | ||
*~ | ||
*.sass-cache | ||
node_modules/ | ||
.tmp/ | ||
|
||
# OS or Editor folders | ||
.DS_Store | ||
Thumbs.db | ||
.cache | ||
.project | ||
.settings | ||
.tmproj | ||
*.esproj | ||
nbproject | ||
*.sublime-project | ||
*.sublime-workspace | ||
*.komodoproject | ||
.komodotools | ||
_notes | ||
dwsync.xml | ||
|
||
# Environmental variables | ||
.env | ||
|
||
# Virtual enviroment | ||
ENV/ | ||
|
||
### Django ### | ||
*.sqlite3 | ||
|
||
#passwords | ||
passwords.txt | ||
|
||
# spotipy lib | ||
token.txt | ||
.cache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
MY_LINKEDIN_EMAIL = "YOUR.EMAIL@gmail.com" | ||
MY_LINKEDIN_PASSWORD = "Your_password" |
Binary file added
BIN
+11.3 MB
Automating_job_applications_on_linkedin/ChromeDriver/chromedriver.exe
Binary file not shown.
2 changes: 2 additions & 0 deletions
2
Automating_job_applications_on_linkedin/ChromeDriver/notes.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
---------ChromeDriver 104.0.5112.79 (2022-08-03)--------- | ||
Supports Chrome version 104 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# Automating_job_applications_on_linkedin | ||
|
||
This is an automated job application bot. The program will use selenium WebDriver | ||
to automate applying for jobs on LinkedIn with the "Easy Apply" function to send applications to all the jobs that meet your criteria (instead of just a single listing). | ||
In the first step, it will log in to your LinkedIn account, and then go to the specific search job URL defined in the program by the user. | ||
After accessing this URL, the bot will go through each of the application and asses if there is a function of Easy Apply. | ||
If it doesn't exist, the job application will be skipped, and the bot will move to the next job application. | ||
After finding the Easy Apply button, the bot will submit the first step of application by pressing it. | ||
In the next step, the bot will validate how the application form looks. | ||
If the application form will have the button next which indicates a multistep application, the bot will terminate the application, | ||
only application with "submit application" will be accepted. | ||
The bot will submit the application, and fill in the given phone number and send out the application. | ||
After that, the bot will move to the next job application. | ||
|
||
|
||
|
||
Necessary steps to make the program work:</br> | ||
1. Install Chrome browser https://www.google.com/intl/en_uk/chrome/ </br> | ||
2. Download chrome driver (don't forget to match the version of your chrome with the version of the chrome driver) https://chromedriver.storage.googleapis.com/index.html?path=104.0.5112.79/, and unzip the file for your OS. | ||
Mark the DIR to the chromedriver.exe file and adjust the *chrome_driver_path* in main.py. </br> | ||
3. Sign up to LinkedIn https://www.linkedin.com/ and configure your Profile. </br> | ||
Make sure you've signed up to LinkedIn and save your email and password somewhere for later use.</br> | ||
Upload your resume by going to Me -> Settings & Privacy -> Data Privacy -> Job Seeking Preferences -> Job Application Settings.</br> | ||
NOTE: Do not enable 2-factor authentication/phone number verification while we are using Selenium.</br> | ||
4. After creating the LinkedIn account, we have to change the name of .env.example to .env and define the environmental variables according to our account:</br> | ||
MY_LINKEDIN_EMAIL = "YOUR.EMAIL@gmail.com"</br> | ||
MY_LINKEDIN_PASSWORD = "Your_password"</br> | ||
5. The user has to adjust the starting variables in the main.py:</br> | ||
*PHONE_NUMBER* - phone number to be filled in the form during application.</br> | ||
*WEBSITE_URL_FOR_THE_DRIVER* - URL for job search.</br> | ||
|
||
|
||
--- | ||
|
||
Example of view Easy Apply application:</br> | ||
![Screenshot](docs/img/01_easy_apply.png)</br> | ||
|
||
|
||
Example of view of submitting application:</br> | ||
![Screenshot](docs/img/02_submiting_applicatio.png)</br> | ||
|
||
|
||
Example of view of invalid form with next button - multistep application is not supported:</br> | ||
![Screenshot](docs/img/03_inalid_form_next.png)</br> | ||
|
||
--- | ||
|
||
|
||
**The program was developed using python 3.10.6, selenium** | ||
|
||
|
||
In order to run the program, you have to execute main.py. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+100 KB
Automating_job_applications_on_linkedin/docs/img/02_submiting_applicatio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+62.9 KB
Automating_job_applications_on_linkedin/docs/img/03_inalid_form_next.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
from selenium import webdriver | ||
from selenium.common.exceptions import NoSuchElementException | ||
from selenium.webdriver.common.by import By | ||
from selenium.webdriver.common.keys import Keys | ||
import time | ||
|
||
# env variables ! | ||
from dotenv import load_dotenv | ||
load_dotenv() | ||
import os | ||
|
||
################################################################################ | ||
## sensitive data ### | ||
##################### | ||
# user defined email and app password for your linkedin account ! | ||
# env variables ! - dont change here ! | ||
MY_LINKEDIN_EMAIL = os.environ.get('MY_LINKEDIN_EMAIL') | ||
MY_LINKEDIN_PASSWORD = os.environ.get('MY_LINKEDIN_PASSWORD') | ||
PHONE_NUMBER = "555555555" # user defined number | ||
################################################################################ | ||
|
||
|
||
####################### SELENIUM SETTINGS ######################### | ||
# adjust this path to wherever you have unpacked the chrome driver file ! | ||
# dont forget that the verion of chrom drive has to match the verison of chrome browser | ||
# https://chromedriver.chromium.org/downloads | ||
# relative path you can use as well absolute path ! | ||
chrome_driver_path = "ChromeDriver/chromedriver.exe" | ||
|
||
# creating the webdriver | ||
driver = webdriver.Chrome(executable_path=chrome_driver_path) | ||
# website url for the linkin job search with eaasy to apply status | ||
# exampel url for web developer search | ||
WEBSITE_URL_FOR_THE_DRIVER = "https://www.linkedin.com/jobs/search/?f_LF=f_AL&geoId=102257491&keywords=web%20developer&location=London%2C%20England%2C%20United%20Kingdom&redirect=false&position=1&pageNum=0" | ||
# load the page at the given URL | ||
driver.get(WEBSITE_URL_FOR_THE_DRIVER) | ||
####################################################################### | ||
|
||
# wait for the page to load | ||
time.sleep(2) | ||
|
||
###### login in to linked in account - after accesing the website ##### | ||
login_button_element = driver.find_element(By.XPATH,'/html/body/div[3]/header/nav/div/a[2]') | ||
login_button_element.click() | ||
|
||
# wait for the page to load | ||
time.sleep(5) | ||
|
||
################### log in pag - login with the user credentials ############ | ||
login_email_input_element = driver.find_element(By.NAME, 'session_key') | ||
login_email_input_element.send_keys(MY_LINKEDIN_EMAIL) | ||
|
||
login_password_input_element = driver.find_element(By.NAME, 'session_password') | ||
login_password_input_element.send_keys(MY_LINKEDIN_PASSWORD) | ||
login_password_input_element.send_keys(Keys.ENTER) | ||
|
||
# wait for the page to load | ||
time.sleep(5) | ||
|
||
# getting all the jobs from the one page | ||
# jobs_list_elements = driver.find_elements(By.CSS_SELECTOR,'.job-card-container--clickable') | ||
jobs_list_elements = driver.find_elements(By.CSS_SELECTOR,'div.job-card-container--clickable') | ||
|
||
print(len(jobs_list_elements)) | ||
# selecting job by job card | ||
for job_element in jobs_list_elements: | ||
# selectic the job card | ||
job_element.click() | ||
|
||
# wait for the page to load | ||
time.sleep(1) | ||
|
||
try: | ||
# hit the easy apply button | ||
easy_apply_button_element = driver.find_element(By.CSS_SELECTOR, 'div.jobs-apply-button--top-card button') | ||
easy_apply_button_element.click() | ||
|
||
# wait for the page to load | ||
time.sleep(2) | ||
|
||
# input phone number and continue | ||
phone_input_element = driver.find_element(By.CLASS_NAME,'fb-single-line-text__input') | ||
if phone_input_element.text == "": # if empty write down the phone number | ||
phone_input_element.send_keys(PHONE_NUMBER) | ||
|
||
# getting the submit button | ||
submit_button_element = driver.find_element(By.CSS_SELECTOR,'footer button') | ||
|
||
# checking if this is the right button | ||
# we are discarding multi step applications | ||
# only submit will be accepted | ||
if submit_button_element.get_attribute('aria-label') == 'Submit application': | ||
# submitting our application | ||
submit_button_element.click() | ||
|
||
# wait for the page to load | ||
time.sleep(3) | ||
|
||
# close the confirmation of submiting application | ||
close_application_element = driver.find_element(By.CLASS_NAME,'artdeco-modal__dismiss') | ||
close_application_element.click() | ||
|
||
# wait for the page to load | ||
time.sleep(2) | ||
|
||
else: | ||
# if the button is next we will close the appliction | ||
close_application_element = driver.find_element(By.CLASS_NAME,'artdeco-modal__dismiss') | ||
close_application_element.click() | ||
# wait for the page to load | ||
time.sleep(2) | ||
|
||
# pressing the discard button | ||
discard_application_element = driver.find_element(By.CLASS_NAME,'artdeco-modal__confirm-dialog-btn') | ||
discard_application_element.click() | ||
# wait for the page to load | ||
time.sleep(2) | ||
|
||
except NoSuchElementException: | ||
print("No application button, skipped.") | ||
continue | ||
|
||
print("done") | ||
# close the browser | ||
driver.quit() # this will close the whole browser |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Python 3.10.6 |