added sorting feature

This commit is contained in:
Vishwa Gaurav
2022-06-29 15:51:43 +05:30
parent 6c1b7b0165
commit 3cc6d63dec

318
index.js
View File

@@ -1,89 +1,96 @@
const cheerio = require('cheerio') const cheerio = require("cheerio");
const axios = require('axios') const axios = require("axios");
module.exports.query = (queryObject) => { module.exports.query = (queryObject) => {
const query = new Query(queryObject) const query = new Query(queryObject);
console.log(query.url(0)) console.log(query.url(0));
return query.getJobs() return query.getJobs();
} };
//transfers object values passed to our .query to an obj we can access //transfers object values passed to our .query to an obj we can access
function Query (queryObj){ function Query(queryObj) {
//query vars //query vars
this.host = queryObj.host || 'www.linkedin.com' this.host = queryObj.host || "www.linkedin.com";
//api handles strings with spaces by replacing the values with %20 //api handles strings with spaces by replacing the values with %20
this.keyword = queryObj.keyword.replace(' ', '+') || '' this.keyword = queryObj.keyword.replace(" ", "+") || "";
this.location = queryObj.location.replace(' ', '+') || '' this.location = queryObj.location.replace(" ", "+") || "";
this.dateSincePosted = queryObj.dateSincePosted || '' this.dateSincePosted = queryObj.dateSincePosted || "";
this.jobType = queryObj.jobType || '' this.jobType = queryObj.jobType || "";
this.remoteFilter = queryObj.remoteFilter || '' this.remoteFilter = queryObj.remoteFilter || "";
this.salary = queryObj.salary || '' this.salary = queryObj.salary || "";
this.experienceLevel = queryObj.experienceLevel || '' this.experienceLevel = queryObj.experienceLevel || "";
//internal variable //internal variable
this.limit = Number(queryObj.limit) || 0 this.limit = Number(queryObj.limit) || 0;
} }
/* /*
* *
* *
* Following get Functions act as object literals so the query can be constructed with the correct parameters * Following get Functions act as object literals so the query can be constructed with the correct parameters
* *
* *
*/ */
Query.prototype.getDateSincePosted = function(){ Query.prototype.getDateSincePosted = function () {
const dateRange = { const dateRange = {
'past month': 'r2592000', "past month": "r2592000",
'past week': 'r604800', "past week": "r604800",
'24hr': 'r86400', "24hr": "r86400",
} };
return dateRange[this.dateSincePosted.toLowerCase()] ?? '' return dateRange[this.dateSincePosted.toLowerCase()] ?? "";
} };
Query.prototype.getExperienceLevel = function(){ Query.prototype.getExperienceLevel = function () {
const experienceRange = { const experienceRange = {
'internship': '1', internship: "1",
'entry level': '2', "entry level": "2",
'associate': '3', associate: "3",
'senior': '4', senior: "4",
'director': '5', director: "5",
'executive': '6', executive: "6",
} };
return experienceRange[this.experienceLevel.toLowerCase()] ?? '' return experienceRange[this.experienceLevel.toLowerCase()] ?? "";
} };
Query.prototype.getJobType = function(){ Query.prototype.getJobType = function () {
const jobTypeRange = { const jobTypeRange = {
'full time': 'F', "full time": "F",
'full-time': 'F', "full-time": "F",
'part time': 'P', "part time": "P",
'part-time': 'P', "part-time": "P",
'contract': 'C', contract: "C",
'temporary': 'T', temporary: "T",
'volunteer': 'V', volunteer: "V",
'internship': 'I' internship: "I",
} };
return jobTypeRange[this.jobType.toLowerCase()] ?? '' return jobTypeRange[this.jobType.toLowerCase()] ?? "";
} };
Query.prototype.getRemoteFilter = function(){ Query.prototype.getRemoteFilter = function () {
const remoteFilterRange = { const remoteFilterRange = {
'on-site':'1', "on-site": "1",
'on site': '1', "on site": "1",
'remote': '2', remote: "2",
'hybrid': '3' hybrid: "3",
} };
return remoteFilterRange[this.remoteFilter.toLowerCase()] ?? '' return remoteFilterRange[this.remoteFilter.toLowerCase()] ?? "";
} };
Query.prototype.getSalary = function(){ Query.prototype.getSalary = function () {
const salaryRange = { const salaryRange = {
'40000': '1', 40000: "1",
'60000': '2', 60000: "2",
'80000': '3', 80000: "3",
'100000': '4', 100000: "4",
'120000': '5', 120000: "5",
} };
return salaryRange[this.salary.toLowerCase()] ?? '' return salaryRange[this.salary.toLowerCase()] ?? "";
} };
Query.prototype.getSortBy = function () {
const sortBy = {
recent: "DD",
relevant: "R",
};
return sortBy[this.salary.toLowerCase()] ?? "";
};
/* /*
* EXAMPLE OF A SAMPLE QUERY * EXAMPLE OF A SAMPLE QUERY
@@ -93,80 +100,95 @@ Query.prototype.getSalary = function(){
* Experience Level(Multiple Picks) f_E * Experience Level(Multiple Picks) f_E
* On-Site/Remote (Multiple Picks) f_WT * On-Site/Remote (Multiple Picks) f_WT
* Salary (Single Pick) f_SB2 * Salary (Single Pick) f_SB2
* *
*/ */
Query.prototype.url = function(start){ Query.prototype.url = function (start) {
let query = `https://${this.host}/jobs-guest/jobs/api/seeMoreJobPostings/search?` let query = `https://${this.host}/jobs-guest/jobs/api/seeMoreJobPostings/search?`;
if(this.keyword !== '') query += `keywords=${this.keyword}` if (this.keyword !== "") query += `keywords=${this.keyword}`;
if(this.location !== '') query += `&location=${this.location}` if (this.location !== "") query += `&location=${this.location}`;
if(this.getDateSincePosted() !== '') query += `&f_TPR=${this.getDateSincePosted()}` if (this.getDateSincePosted() !== "")
if(this.getSalary() !== '') query += `&f_SB2=${this.getSalary()}` query += `&f_TPR=${this.getDateSincePosted()}`;
if(this.getExperienceLevel() !== '') query += `&f_E=${this.getExperienceLevel()}` if (this.getSalary() !== "") query += `&f_SB2=${this.getSalary()}`;
if(this.getRemoteFilter() !== '') query += `&f_WT=${this.getRemoteFilter()}` if (this.getExperienceLevel() !== "")
if(this.getJobType() !== '') query += `&f_JT=${this.getJobType()}` query += `&f_E=${this.getExperienceLevel()}`;
query += `&start=${start}` if (this.getRemoteFilter() !== "") query += `&f_WT=${this.getRemoteFilter()}`;
return encodeURI(query) if (this.getJobType() !== "") query += `&f_JT=${this.getJobType()}`;
} query += `&start=${start}`;
query += `&sortBy=${this.getSortBy}`;
return encodeURI(query);
};
Query.prototype.getJobs = async function(){ Query.prototype.getJobs = async function () {
try { try {
let parsedJobs, resultCount = 1, start = 0, jobLimit = this.limit, allJobs = [] let parsedJobs,
resultCount = 1,
start = 0,
jobLimit = this.limit,
allJobs = [];
while (resultCount > 0) { while (resultCount > 0) {
//fetch our data using our url generator with //fetch our data using our url generator with
//the page to start on //the page to start on
const { data } = await axios.get(this.url(start)) const { data } = await axios.get(this.url(start));
//select data so we can check the number of jobs returned //select data so we can check the number of jobs returned
const $ = cheerio.load(data) const $ = cheerio.load(data);
const jobs = $('li') const jobs = $("li");
//if result count ends up being 0 we will stop getting more jobs //if result count ends up being 0 we will stop getting more jobs
resultCount = jobs.length resultCount = jobs.length;
console.log('I got ', jobs.length, ' jobs') console.log("I got ", jobs.length, " jobs");
//to get the job data as objects with the desired details
parsedJobs = parseJobList(data)
allJobs.push(...parsedJobs)
//increment by 25 bc thats how many jobs the AJAX request fetches at a time //to get the job data as objects with the desired details
start += 25 parsedJobs = parseJobList(data);
allJobs.push(...parsedJobs);
//in order to limit how many jobs are returned
//this if statment will return our function value after looping and removing excess jobs //increment by 25 bc thats how many jobs the AJAX request fetches at a time
if (jobLimit != 0 && allJobs.length > jobLimit){ start += 25;
while(allJobs.length != jobLimit) allJobs.pop()
return allJobs //in order to limit how many jobs are returned
} //this if statment will return our function value after looping and removing excess jobs
if (jobLimit != 0 && allJobs.length > jobLimit) {
} while (allJobs.length != jobLimit) allJobs.pop();
//console.log(allJobs) return allJobs;
return allJobs }
} catch (error) {
console.error(error)
} }
//console.log(allJobs)
return allJobs;
} catch (error) {
console.error(error);
}
};
function parseJobList(jobData) {
const $ = cheerio.load(jobData);
const jobs = $("li");
const jobObjects = jobs
.map((index, element) => {
const job = $(element);
const position = job.find(".base-search-card__title").text().trim() || "";
const company =
job.find(".base-search-card__subtitle").text().trim() || "";
const location =
job.find(".job-search-card__location").text().trim() || "";
const date = job.find("time").attr("datetime") || "";
const salary =
job
.find(".job-search-card__salary-info")
.text()
.trim()
.replace(/\n/g, "")
.replaceAll(" ", "") || "";
const jobUrl = job.find(".base-card__full-link").attr("href") || "";
return {
position: position,
company: company,
location: location,
date: date,
salary: salary,
jobUrl: jobUrl,
};
})
.get();
return jobObjects;
} }
function parseJobList(jobData){
const $ = cheerio.load(jobData)
const jobs = $('li')
const jobObjects = jobs.map((index, element) => {
const job = $(element)
const position = job.find('.base-search-card__title').text().trim() || ''
const company = job.find('.base-search-card__subtitle').text().trim() || ''
const location = job.find('.job-search-card__location').text().trim() || ''
const date = job.find('time').attr('datetime') || ''
const salary = job.find('.job-search-card__salary-info').text().trim().replace(/\n/g, '').replaceAll(' ', '') || ''
const jobUrl = job.find('.base-card__full-link').attr('href') || ''
return {
position: position,
company: company,
location: location,
date: date,
salary: salary,
jobUrl: jobUrl
}
}).get()
return jobObjects
}