Skip to content

Commit

Permalink
Merge pull request nicolomantini#32 from krapes/upload_identifier
Browse files Browse the repository at this point in the history
Resume, Cover letter and Photo support
  • Loading branch information
nicolomantini authored Jul 18, 2020
2 parents 72b52fe + 4a32c68 commit 0035625
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 31 deletions.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ locations:
- # Location you want to search for
- # A second location you want to search in

cover_letter_loctn:
- # '/home/PATH_TO_FILE'
uploads:
Resume: # PATH TO Resume
Cover Letter: # PATH TO cover letter
Photo: # PATH TO photo

output_filename:
- # PATH TO OUTPUT FILE (default output.csv)
Expand All @@ -37,6 +39,11 @@ blacklist:
```
__NOTE: AFTER EDITING SAVE FILE, DO NOT COMMIT FILE__

### Uploads

There is no limit to the number of files you can list in the uploads section.
The program takes the titles from the input boxes and tries to match them with
list in the config file.

## Execute

Expand Down
20 changes: 12 additions & 8 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@ username:
password:

positions:
- # positions you want to search for
- Data Scientist
- # Another position you want to search for
- # A third position you want to search for

locations:
- # Location you want to search for
- Remote
- # A second location you want to search in

cover_letter_loctn:
- # '/home/PATH_TO_FILE'
# --------- Optional Parameters -------
# uploads:
# Resume: # PATH TO Resume
# Cover Letter: # PATH TO cover letter
# Photo: # PATH TO photo

output_filename:
- # PATH TO OUTPUT FILE (default output.csv)

blacklist:
- # Company names you want to ignore
# output_filename:
# - # PATH TO OUTPUT FILE (default output.csv)

# blacklist:
# - # Company names you want to ignore
53 changes: 32 additions & 21 deletions easyapplybot.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ class EasyApplyBot:
MAX_SEARCH_TIME = 10*60



def __init__(self,
username,
password,
cover_letter_loctn=None,
uploads={},
filename='output.csv',
blacklist=[]):

print("\nWelcome to Easy Apply Bot\n")
dirpath = os.getcwd()
print("current directory is : " + dirpath)

self.cover_letter_loctn = cover_letter_loctn
self.appliedJobIDs = self.get_appliedIDs(filename) if self.get_appliedIDs(filename) != None else []
self.uploads = uploads
past_ids = self.get_appliedIDs(filename)
self.appliedJobIDs = past_ids if past_ids != None else []
self.filename = filename
self.options = self.browser_options()
self.browser = driver
Expand All @@ -49,13 +49,12 @@ def __init__(self,


def get_appliedIDs(self, filename):
print(filename)
try:
df = pd.read_csv(filename,
header=None,
names=['timestamp', 'jobID', 'job', 'company', 'attempted', 'result'],
lineterminator='\n',
encoding = 'utf-8')
encoding='utf-8')

df['timestamp'] = pd.to_datetime(df['timestamp'], format="%Y-%m-%d %H:%M:%S.%f")
df = df[df['timestamp'] > (datetime.now() - timedelta(days=2))]
Expand Down Expand Up @@ -91,13 +90,10 @@ def start_linkedin(self,username,password):
except TimeoutException:
print("TimeoutException! Username/password field or login button not found")


def fill_data(self):
self.browser.set_window_size(0, 0)
self.browser.set_window_position(2000, 2000)

print(self.cover_letter_loctn)

def start_apply(self, positions, locations):
start = time.time()
self.fill_data()
Expand Down Expand Up @@ -164,7 +160,6 @@ def applications_loop(self, position, location):
jobIDs = [x for x in IDs if x not in self.appliedJobIDs]
after = len(jobIDs)


if len(jobIDs) == 0 and len(IDs) > 24:
jobs_per_page = jobs_per_page + 25
count_job = 0
Expand Down Expand Up @@ -236,8 +231,7 @@ def re_extract(text, pattern):


def get_job_page(self, jobID):
#root = 'www.linkedin.com'
#if root not in job:

job = 'https://www.linkedin.com/jobs/view/'+ str(jobID)
self.browser.get(job)
self.job_page = self.load_page(sleep=0.5)
Expand All @@ -264,7 +258,6 @@ def is_present(button_locator):

try:
time.sleep(random.uniform(1.5, 2.5))
#print(f"Navigating... ")
next_locater = (By.CSS_SELECTOR,
"button[aria-label='Continue to next step']")
review_locater = (By.CSS_SELECTOR,
Expand All @@ -275,17 +268,28 @@ def is_present(button_locator):
"button[aria-label='Submit application']")
error_locator = (By.CSS_SELECTOR,
"p[data-test-form-element-error-message='true']")
cover_letter = (By.CSS_SELECTOR, "input[name='file']")
upload_locator = (By.CSS_SELECTOR, "input[name='file']")



submitted = False
while True:

# Upload Cover Letter if possible
if is_present(cover_letter):
input_button = self.browser.find_elements(cover_letter[0],
cover_letter[1])
if is_present(upload_locator):

input_button[0].send_keys(self.cover_letter_loctn)
input_buttons = self.browser.find_elements(upload_locator[0],
upload_locator[1])
for input_button in input_buttons:
parent = input_button.find_element(By.XPATH, "..")
sibling = parent.find_element(By.XPATH, "preceding-sibling::*")
grandparent = sibling.find_element(By.XPATH, "..")
for key in self.uploads.keys():
if key in sibling.text or key in grandparent.text:
input_button.send_keys(self.uploads[key])


#input_button[0].send_keys(self.cover_letter_loctn)
time.sleep(random.uniform(4.5, 6.5))

# Click Next or submitt button if possible
Expand Down Expand Up @@ -367,6 +371,9 @@ def next_jobs_page(self, position, location, jobs_per_page):
def finish_apply(self):
self.browser.close()




if __name__ == '__main__':

with open("config.yaml", 'r') as stream:
Expand All @@ -382,13 +389,17 @@ def finish_apply(self):


print(parameters)
cover_letter_loctn = parameters.get('cover_letter_loctn', [None])[0]
output_filename = parameters.get('output_filename', ['output.csv'])[0]

output_filename = [f for f in parameters.get('output_filename', ['output.csv']) if f != None]
output_filename = output_filename[0] if len(output_filename) > 0 else 'output.csv'
blacklist = parameters.get('blacklist', [])
uploads = parameters.get('uploads', {})
for key in uploads.keys():
assert uploads[key] != None

bot = EasyApplyBot(parameters['username'],
parameters['password'],
cover_letter_loctn=cover_letter_loctn,
uploads=uploads,
filename=output_filename,
blacklist=blacklist
)
Expand Down

0 comments on commit 0035625

Please sign in to comment.