Skip to content

Instantly share code, notes, and snippets.

@sagunsh
Created March 8, 2025 02:47
Show Gist options
  • Save sagunsh/28e927c0407dcb26c65c68572b963312 to your computer and use it in GitHub Desktop.
Save sagunsh/28e927c0407dcb26c65c68572b963312 to your computer and use it in GitHub Desktop.
Monitor jobs on seek
# author: sagunsh
# description: monitor jobs on seek.com.au
# requires: python 3.6+
#
# Usage
# help: python seek_monitoring.py --help
# print to console: python seek_monitoring.py --keyword="software engineer"
# save to csv (50 jobs): python seek_monitoring.py --keyword="software engineer" --max=50 --csv
# todo: send email
import argparse
import json
import csv
import urllib.parse
import urllib.request
BASE_URL = 'https://www.seek.com.au/'
SEARCH_PATH = '/api/jobsearch/v5/search'
def get_response(url, max_retries=10):
retry = 0
headers = {
'accept': 'application/json, text/plain, */*',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
}
while retry < max_retries:
try:
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req, timeout=30) as response:
return response.read().decode()
except:
pass
retry += 1
def search_jobs(keyword, max_count):
if not isinstance(keyword, str) or len(keyword) == 0:
return []
if not isinstance(max_count, int) or max_count <= 0 or max_count > 100:
max_count = 25
params = {
'page': '1',
'keywords': keyword,
'pageSize': max_count,
'sortmode': 'KeywordRelevance', # or 'ListedDate'
}
search_url = urllib.parse.urljoin(BASE_URL, SEARCH_PATH + '?' + urllib.parse.urlencode(params))
try:
response = get_response(search_url)
jobs = json.loads(response).get('data', [])
except:
jobs = []
results = []
for job in jobs:
job_dict = {
'title': job.get('title'),
'url': 'https://www.seek.com.au/job/' + job.get('id'),
'company': job.get('advertiser').get('description'),
'posted_on': job.get('listingDate').split('T')[0],
'salary': job.get('salaryLabel'),
}
results.append(job_dict)
return results
def generate_html_table(data):
if len(data) == 0:
return '<p>No data available</p>'
headers = data[0].keys()
html = '<table border="1" cellspacing="0" cellpadding="5" style="border-collapse: collapse;">'
html += '<tr>'
for header in headers:
if header != 'url':
html += f'<th style="background-color: #f2f2f2; padding: 8px; text-align: left;">{header.title()}</th>'
html += '</tr>'
for row in data:
html += '<tr>'
for key in headers:
if key == 'title':
html += f'<td style="padding: 8px;"><a href="{row["url"]}" target="_blank">{row[key]}</a></td>'
elif key == 'url':
continue
else:
html += f'<td style="padding: 8px;">{row[key]}</td>'
html += '</tr>'
html += '</table>'
return html
def save_to_csv(data):
if len(data) == 0:
return False
file_name = f'seek_jobs.csv'
with open(file_name, 'w') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=jobs[0].keys())
writer.writeheader()
writer.writerows(jobs)
return file_name
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Monitor seek jobs')
parser.add_argument('--keyword', help='Search keyword', default='python developer')
parser.add_argument('--max', help='Max number of jobs', default=25, type=int)
parser.add_argument('--csv', help='Save output to CSV file', action='store_true')
parser.add_argument('--email', help='Send email', action='store_true')
args = parser.parse_args()
print(f'searching for {args.keyword} jobs')
jobs = search_jobs(keyword=args.keyword, max_count=args.max)
if args.csv:
file_name = save_to_csv(jobs)
if file_name:
print(f'Saved to {file_name}')
else:
print('No data available')
if args.email:
html_table = generate_html_table(jobs)
html = f'<html lang="en"><body style="font-family:Tahoma">{html_table}</body></html>'
print(html)
print('\n\nTodo: Send email to myself')
if not args.csv and not args.email:
for job in jobs:
print(job)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment