Automate Your Naukri Profile with Python and Selenium

Supercharge Your Job Search at Naukri.com

Kuharan Bhowmik
8 min readOct 18, 2023

--

A picture of Gurudongmar lake in Sikkim, India
https://unsplash.com/photos/ne2LanLdjd8

Are you tired of the daily grind? Sick of monotonous tasks, like updating your Naukri profile and uploading your resume for the recruiters daily? Well, today, I am going to show you how to be a lazy engineer and let Python do the work for you. We’ve all heard of “working smarter, not harder,” and in this blog post, we’ll take that to heart by automating the mundane tasks of keeping your Naukri profile up-to-date.

The Boring Naukri Routine

Before we embark on this journey of tech hilarity, let’s acknowledge the tedious tasks we’re automating. Every morning, many of us wake up, sip our coffee, and open Naukri.com to update our profiles and upload our resumes before the recruiters start their hunt. It’s not that these tasks are complicated; they’re just mind-numbingly repetitive just because we want to appear on the top of their search list.

Meet Our Hero: Python with Selenium

To begin, we need to introduce you to our hero, Python, accompanied by its trusty sidekick, Selenium. Now, let’s dive into the code, chunk by chunk, to understand how we’ll achieve this engineering miracle.

Module Mash-Up

Here, we import various Python modules to work our magic. Selenium will be our web automation tool, and PyPDF2 will help us manipulate PDF files. The other modules help with various tasks, such as generating random text for the resume, error handling, time, and logging.

# Import the necessary modules
import os
import io
import sys
import time
import logging
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support import expected_conditions as EC
from PyPDF2 import PdfReader, PdfWriter
from string import ascii_uppercase, digits
from random import choice, randint
from datetime import datetime
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
import random
import traceback

Configuration Choices

In this section, you need to set the path to your original resume and the path where the modified resume will be saved. Don’t forget to add your Naukri username and password, and if you want to add random hidden characters to your resume (a trick to fool the hash algorithms), set `updatePDF` to `True`.

# Add folder Path of your resume
originalResumePath = r"Resume.pdf"
# Add Path where the modified resume should be saved
modifiedResumePath = r"modified_resume.pdf"

# Update your Naukri username and password here before running
username = ""
password = ""

# False if you don’t want to add random HIDDEN chars to your resume
updatePDF = True

Now, let’s move on to the action-packed functions that make our automation possible.

Logging and Error Handling

Before we dive into the action, let’s ensure that we have a record of our hero’s adventures. This `log_msg` function will print messages to the console and store them in a log file.

def log_msg(message):
"""Print to console and store to Log"""
print(message)
logging.info(message)

And because even heroes can face adversity, we have the `catch` function to catch errors and log their details.

def catch(error):
"""Method to catch errors and log error details"""
exc_type, exc_obj, exc_tb = sys.exc_info()
lineNo = str(exc_tb.tb_lineno)
msg = "%s : %s at Line %s." % (type(error), error, lineNo)
print(msg)
logging.error(msg)

Element Identification and Waiting

Our hero needs to locate elements on the web page, right? This `getObj` function helps identify elements using different locators like ID, name, XPath, and more.

def getObj(locatorType):
"""This map defines how elements are identified"""
map = {
"ID": By.ID,
"NAME": By.NAME,
"XPATH": By.XPATH,
"TAG": By.TAG_NAME,
"CLASS": By.CLASS_NAME,
"CSS": By.CSS_SELECTOR,
"LINKTEXT": By.LINK_TEXT,
}
return map[locatorType]

To make sure our hero doesn’t get too impatient, we have the `WaitTillElementPresent` and `GetElement` functions. The former waits until an element is present, while the latter retrieves the element.

def WaitTillElementPresent(driver, elementTag, locator="ID", timeout=30):
"""Wait till element present. Default 30 seconds"""
result = False
driver.implicitly_wait(0)
locator = locator.upper()

for i in range(timeout):
time.sleep(0.99)
try:
if is_element_present(driver, getObj(locator), elementTag):
result = True
break
except Exception as e:
log_msg("Exception when WaitTillElementPresent : %s" % e)

if not result:
log_msg("Element not found with %s : %s" % (locator, elementTag))
driver.implicitly_wait(3)
return result

def is_element_present(driver, how, what):
"""Returns True if element is present"""
try:
driver.find_element(by=how, value=what)
except NoSuchElementException:
return False
return True

def GetElement(driver, elementTag, locator="ID"):
"""Wait max 15 secs for element and then select when it is available"""
try:

def _get_element(_tag, _locator):
_by = getObj(_locator)
if is_element_present(driver, _by, _tag):
return WebDriverWait(driver, 10).until(
lambda d: driver.find_element(_by, _tag)
)

element = _get_element(elementTag, locator.upper())
if element:
return element
log_msg("Element not found with %s : %s" % (locator, elementTag))
return None
except Exception as e:
catch(e)
return None

Cleanup Crew

Finally, even heroes need a break. The `tearDown` function is there to gracefully close and quit the browser.


def tearDown(driver):
try:
driver.close()
log_msg("Driver Closed Successfully")
except Exception as e:
catch(e)

try:
driver.quit()
log_msg("Driver Quit Successfully")
except Exception as e:
catch(e)

Dependencies: The Sidekicks

To run this script, we need to enlist the help of some sidekicks. Create a `requirements.txt` file with the following content:

reportlab==4.0.5
webdriver_manager==4.0.1
selenium==4.13.0
pypdf>=3.9.0
pypdf2

You can install these dependencies using `pip` to ensure that Python has all the tools it needs to perform its magic.

The Grand Entry

Our Python hero takes center stage with the `if __name__ == “__main__”:` block. This block serves as the entry point to our script and ensures that the following code is executed when the script is run.

if __name__ == "__main__":
log_msg("-----Naukri.py Script Run Begin-----")
driver = None
try:
status, driver = naukriLogin()
log_msg("-----Naukri.py Login Success-----")
if status:
if os.path.exists(originalResumePath):
if updatePDF:
resumePath = UpdateResume()
UploadResume(driver, resumePath)
else:
UploadResume(driver, originalResumePath)
else:
log_msg("Resume not found at %s " % originalResumePath)

except Exception as e:
catch(e)

finally:
tearDown(driver)

log_msg("-----Naukri.py Script Run Ended-----\n")

Morning Coffee — Login to Naukri

The first task is to log in to Naukri. Our hero Python calls the `naukriLogin` function, which returns a status and a Selenium WebDriver instance.

def naukriLogin(headless=False):
"""Open Chrome browser and Login to Naukri.com"""
status = False
driver = None

try:
driver = LoadNaukri(headless)

if "naukri" in driver.title.lower():
log_msg("Website Loaded Successfully.")

emailFieldElement = None
if is_element_present(driver, By.ID, "emailTxt"):
emailFieldElement = GetElement(driver, "emailTxt", locator="ID")
passFieldElement = GetElement(driver, "pwd1", locator="ID")
loginXpath = "//*[@type='submit' and @value='Login']"
loginButton = GetElement(driver, loginXpath, locator="XPATH")

elif is_element_present(driver, By.ID, "usernameField"):
emailFieldElement = GetElement(
driver, "usernameField", locator="ID")
passFieldElement = GetElement(
driver, "passwordField", locator="ID")
loginXpath = '//*[@type="submit"]'
loginButton = GetElement(driver, loginXpath, locator="XPATH")

else:
log_msg("None of the elements found to login.")

if emailFieldElement is not None:
emailFieldElement.clear()
emailFieldElement.send_keys(username)
passFieldElement.clear()
passFieldElement.send_keys(password)
loginButton.send_keys(Keys.ENTER)
status = True

except Exception as e:
catch(e)
return (status, driver)

The `naukriLogin` function opens a Chrome browser and loads the Naukri login page. It checks if the page title contains “naukri,” indicating that the website loaded successfully. Then, it fills in your username and password, which you provided earlier, and clicks the login button. If all goes well, you’re logged in!

The Mysterious LoadNaukri Function

Behind the scenes, our hero relies on the `LoadNaukri` function to open Chrome with the necessary settings.

def LoadNaukri(headless):
"""Open Chrome to load Naukri.com"""
options = webdriver.ChromeOptions()
options.add_argument("--disable-notifications")
options.add_argument("--start-maximized") # ("--kiosk") for MAC
options.add_argument("--disable-popups")
options.add_argument("--disable-gpu")
if headless:
options.add_argument("--disable-dev-shm-usage")
options.add_argument("headless")

# updated to use ChromeDriverManager to match correct chromedriver automatically
driver = webdriver.Chrome(options=options)
log_msg("Google Chrome Launched!")

driver.get(NaukriURL)
return driver

The `LoadNaukri` function configures the Chrome browser to start in a maximized window, disables notifications and pop-ups, and, if in headless mode, uses additional options to prevent shared memory usage. The function returns a Chrome WebDriver instance, all set up to navigate Naukri.com.

Now that you’re logged in, it’s time to update your resume.

Update Your Resume

def UpdateResume():
try:
# random text with with random location and size
txt = randomText()
xloc = randint(700, 1000) # this ensures that text is 'out of page'
fsize = randint(1, 10)

packet = io.BytesIO()
can = canvas.Canvas(packet, pagesize=letter)
can.setFont("Helvetica", fsize)
can.drawString(xloc, 100, "lon")
can.save()

packet.seek(0)
new_pdf = PdfReader(packet)
existing_pdf = PdfReader(open(originalResumePath, "rb"))
pagecount = len(existing_pdf.pages)
print("Found %s pages in PDF" % pagecount)

output = PdfWriter()
# Merging new pdf with last page of my existing pdf
# Updated to get last page for pdf files with varying page count
for pageNum in range(pagecount - 1):
output.addPage(existing_pdf.getPage(pageNum))

page = existing_pdf.pages[pagecount - 1]
page.merge_page(new_pdf.pages[0])
output.add_page(page)
# save the new resume file
with open(modifiedResumePath, "wb") as outputStream:
output.write(outputStream)
print("Saved modified PDF : %s" % modifiedResumePath)
return os.path.abspath(modifiedResumePath)
except Exception as e:
catch(e)
return os.path.abspath(originalResumePath)

The `UpdateResume` function performs some resume magic. It generates random text and places it at a random location on the last page of your original resume. Why? Well, it’s just for fun! If you don’t want this, you can set `updatePDF` to `False` earlier in the script.

The Magic of UploadResume

With your modified resume in hand, it’s time to upload it to Naukri.

def UploadResume(driver, resumePath):
try:
attachCVID = "attachCV"
CheckPointXpath = "//*[contains(@class, 'updateOn')]"
driver.get("https://www.naukri.com/mnjuser/profile")
current_url = driver.current_url
# Print the current URL
print("Current URL:", current_url)
try:
WaitTillElementPresent(driver, attachCVID, locator="ID")
AttachElement = GetElement(driver, attachCVID, locator="ID")
AttachElement.send_keys(resumePath)
except Exception as e:
log_msg(f"Error: {e}")
traceback.print_exc()

WaitTillElementPresent(driver, CheckPointXpath, locator="XPATH")
CheckPoint = GetElement(driver, CheckPointXpath, locator="XPATH")
if CheckPoint:
LastUpdatedDate = CheckPoint.text
todaysDate1 = datetime.today().strftime("%b %d, %Y")
todaysDate2 = datetime.today().strftime("%b %#d, %Y")
if todaysDate1 in LastUpdatedDate or todaysDate2 in LastUpdatedDate:
log_msg(
"Resume Document Upload Successful. Last Updated date = %s"
% LastUpdatedDate
)
else:
log_msg(
"Resume Document Upload failed. Last Updated date = %s"
% LastUpdatedDate
)
else:
log_msg("Resume Document Upload failed. Last Updated date not found.")

The `UploadResume` function takes care of this. It locates the elements for uploading the resume, attaches the modified resume, and checks if the last update date reflects your changes. If everything goes well, you’re all set with an updated resume on Naukri.

Adding a Personal Touch to Your Profile

To make your Naukri profile unique, our hero Python even adds a random job description to your profile summary.

data_engineer_descriptions = [
#profile summaries
]

driver.execute_script("window.scrollBy(0, 500);")

selected_description = random.choice(data_engineer_descriptions)
print(selected_description)

summaryeditxpath = """//*[@id="lazyResumeHead"]/div/div/div[1]/span[2]"""
if WaitTillElementPresent(driver, summaryeditxpath, locator="XPATH"):
GetElement(driver, summaryeditxpath, locator="XPATH").click()
log_msg("Summary Click Successful")

summaryboxxpath = """//*[@id="resumeHeadlineTxt"]"""
if WaitTillElementPresent(driver, summaryboxxpath, locator="XPATH"):
textbox = GetElement(driver, summaryboxxpath, locator="XPATH")
textbox.clear()
textbox.send_keys(selected_description)
log_msg("Summary box Click Successful")

savexpath = """//button[@class='btn-dark-ot' and @type='submit' and contains(text(), 'Save')]"""
if WaitTillElementPresent(driver, savexpath, locator="XPATH"):
GetElement(driver, savexpath, locator="XPATH").click()
log_msg("Summary save button Click Successful")

except Exception as e:
catch(e)

Our Python hero scrolls down the page, selects the summary section, and adds a randomly selected job description. The magic touch is complete with a click on the “Save” button.

Running the Script

To run the script, follow these steps:

1. Ensure you have the required dependencies installed. You can use `pip` to install them:

pip install -r requirements.txt

2. Customize the script by setting your original and modified resume paths, Naukri username, and password. You can also choose whether to add random hidden characters to your resume by modifying the `updatePDF` variable.

# Add folder Path of your resume
originalResumePath = r”Resume.pdf”

# Add Path where the modified resume should be saved
modifiedResumePath = r”modified_resume.pdf”

# Update your Naukri username and password here before running
username = “”
password = “”

# False if you don’t want to add random HIDDEN chars to your resume
updatePDF = True

3. Save your changes and run the script using Python:

python naukri.py

The script will launch Chrome, log in to Naukri, update your resume (if you want), and even add a fun job description to your profile summary. All you need to do is sit back and enjoy your coffee while Python does the work!

Thank you for joining me on this hilarious journey through the world of tech automation. I hope you’ve had a good laugh and maybe even learned a thing or two about Python and Selenium.

Disclaimer: This blog post is a work of humor and satire. Please use the code responsibly and in compliance with Naukri’s terms and conditions.

PS: I am open to work — https://www.linkedin.com/in/kuharan/

--

--