mirror of
https://github.com/hmalik144/Automation---ReedJobApplications.git
synced 2025-12-10 03:05:30 +00:00
Added excel file upon completion
This commit is contained in:
58
.idea/artifacts/JobApplications_jar.xml
generated
Normal file
58
.idea/artifacts/JobApplications_jar.xml
generated
Normal file
@@ -0,0 +1,58 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact type="jar" name="JobApplications:jar">
|
||||
<output-path>$PROJECT_DIR$/out/artifacts/JobApplications_jar</output-path>
|
||||
<root id="archive" name="JobApplications.jar">
|
||||
<element id="module-output" name="JobApplications" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml/4.1.1/poi-ooxml-4.1.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/io/github/microutils/kotlin-logging/1.6.22/kotlin-logging-1.6.22.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/io/github/microutils/kotlin-logging-common/1.6.22/kotlin-logging-common-1.6.22.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/codehaus/mojo/animal-sniffer-annotations/1.14/animal-sniffer-annotations-1.14.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-compress/1.19/commons-compress-1.19.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-ie-driver/3.141.59/selenium-ie-driver-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-java/3.141.59/selenium-java-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/tylerthrailkill/helpers/pretty-print/2.0.2/pretty-print-2.0.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-core/1.3.0-alpha4/logback-core-1.3.0-alpha4.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-firefox-driver/3.141.59/selenium-firefox-driver-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.3.61/kotlin-stdlib-1.3.61.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-remote-driver/3.141.59/selenium-remote-driver-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/sun/mail/javax.mail/1.6.0/javax.mail-1.6.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.13/commons-codec-1.13.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/guava/guava/25.0-jre/guava-25.0-jre.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi-ooxml-schemas/4.1.1/poi-ooxml-schemas-4.1.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/ch/qos/logback/logback-classic/1.3.0-alpha4/logback-classic-1.3.0-alpha4.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.61/kotlin-stdlib-jdk7-1.3.61.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/xmlbeans/xmlbeans/3.1.0/xmlbeans-3.1.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-opera-driver/3.141.59/selenium-opera-driver-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/squareup/retrofit2/retrofit/2.6.0/retrofit-2.6.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-exec/1.3/commons-exec-1.3.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-api/3.141.59/selenium-api-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/ibm/icu/icu4j/63.1/icu4j-63.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/squareup/retrofit2/converter-gson/2.6.0/converter-gson-2.6.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.0.0/checker-compat-qual-2.0.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/squareup/okio/okio/1.14.0/okio-1.14.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/bytebuddy/byte-buddy/1.8.15/byte-buddy-1.8.15.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-edge-driver/3.141.59/selenium-edge-driver-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/gson/gson/2.8.5/gson-2.8.5.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/json/json/20190722/json-20190722.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.61/kotlin-stdlib-jdk8-1.3.61.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/virtuald/curvesapi/1.06/curvesapi-1.06.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-support/3.141.59/selenium-support-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/javax/activation/activation/1.1/activation-1.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.3.3/kotlinx-coroutines-core-1.3.3.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/poi/poi/4.1.1/poi-4.1.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-safari-driver/3.141.59/selenium-safari-driver-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/squareup/okhttp3/okhttp/3.11.0/okhttp-3.11.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.1.3/error_prone_annotations-2.1.3.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-simple/1.6.1/slf4j-simple-1.6.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-collections4/4.4/commons-collections4-4.4.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/seleniumhq/selenium/selenium-chrome-driver/3.141.59/selenium-chrome-driver-3.141.59.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.61/kotlin-stdlib-common-1.3.61.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.8.0-beta1/slf4j-api-1.8.0-beta1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.3.11/kotlin-reflect-1.3.11.jar" path-in-jar="/" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
8
pom.xml
8
pom.xml
@@ -75,6 +75,12 @@
|
||||
<artifactId>kotlinx-coroutines-core</artifactId>
|
||||
<version>1.3.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-reflect</artifactId>
|
||||
<version>1.3.61</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -119,6 +125,8 @@
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<classpathPrefix>lib/</classpathPrefix>
|
||||
<mainClass>Main</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import api.network.responses.ReedJobObject
|
||||
import java.time.LocalDateTime
|
||||
import java.util.*
|
||||
|
||||
data class JobObject(
|
||||
@@ -10,7 +12,12 @@ data class JobObject(
|
||||
var dateApplied : String? = null
|
||||
){
|
||||
|
||||
override fun toString(): String {
|
||||
return super.toString()
|
||||
}
|
||||
constructor(job: ReedJobObject): this(
|
||||
jobId = job.jobId.toString(),
|
||||
website = job.jobUrl,
|
||||
jobTitle = job.jobTitle,
|
||||
location = job.locationName,
|
||||
company = job.employerName,
|
||||
dateApplied = LocalDateTime.now().toString()
|
||||
)
|
||||
}
|
||||
@@ -11,111 +11,111 @@ import kotlin.math.roundToInt
|
||||
|
||||
fun StartSearch(){
|
||||
|
||||
//Open Chrome
|
||||
System.setProperty("webdriver.chrome.driver","C:\\Selenium\\selenium-java-3.141.59\\chromedriver_win32\\chromedriver.exe" )
|
||||
val driver = ChromeDriver()
|
||||
|
||||
//open reed website login
|
||||
driver.get("https://www.reed.co.uk/account/signin?returnUrl=%2F#&card=signin")
|
||||
val wait = WebDriverWait(driver, 20)
|
||||
|
||||
//wait for page to load
|
||||
val lastElementToLoad = driver.findElementById("signin-button")
|
||||
wait.until(ExpectedConditions.elementToBeClickable(lastElementToLoad))
|
||||
|
||||
//insert credentials and sign in
|
||||
driver.findElementByXPath("//*[@id=\"Credentials_Email\"]").sendKeys(REED_USERNAME)
|
||||
driver.findElementByXPath("//*[@id=\"Credentials_Password\"]").sendKeys(REED_PASSWORD)
|
||||
lastElementToLoad.click()
|
||||
|
||||
//wait for page to load
|
||||
val jobSearchEditText = driver.findElementByXPath("//*[@id=\"keywords\"]")
|
||||
wait.until(ExpectedConditions.elementToBeClickable(jobSearchEditText))
|
||||
|
||||
// //submit search
|
||||
jobSearchEditText.sendKeys(REED_KEYWORDS)
|
||||
driver.findElementByXPath("//*[@id=\"location\"]").sendKeys(REED_LOCATION)
|
||||
driver.findElementByXPath("//*[@id=\"main-search\"]/div[1]/div[3]/button").click()
|
||||
|
||||
//todo: change to wait
|
||||
Thread.sleep(1500)
|
||||
|
||||
val ad = driver.findElementByXPath("//*[@id=\"content\"]/div[1]/div[2]/h1")
|
||||
wait.until(ExpectedConditions.elementToBeClickable(ad))
|
||||
|
||||
//find number of pages
|
||||
val text = driver.findElementByCssSelector("div.page-counter").text /* eg. 1 - 25 of 99 jobs */
|
||||
print(text)
|
||||
val count = text.toTotalCount()
|
||||
val pages = count.getNumberOfPages()
|
||||
|
||||
//loop through pages of search
|
||||
for (i in 1..pages){
|
||||
|
||||
//open page by number on search
|
||||
//todo: change this url builder
|
||||
driver.get("https://www.reed.co.uk/jobs/android-developer-jobs-in-kilburn-london?pageno=$i")
|
||||
Thread.sleep(2500)
|
||||
|
||||
//elements list of jobs on page
|
||||
val list = driver.findElementsByCssSelector("div.col-sm-12.col-md-9.col-lg-10.details")
|
||||
|
||||
//turn list into global list job object
|
||||
list.forEach {
|
||||
val badge = it.findElement(By.cssSelector("div.badge-container"))
|
||||
//check if there is a badge element
|
||||
if (badge.isDisplayed){
|
||||
//see if applied is in badge
|
||||
val applied = badge.findElements(By.cssSelector("span.label.label-applied"))
|
||||
//if applied doesnt exist then add to global list of jobs
|
||||
if (applied.isNullOrEmpty()){
|
||||
val jobObject = it.toJobObject()
|
||||
jobsList.add(jobObject)
|
||||
}
|
||||
|
||||
}else{
|
||||
//no badge exists so add to list of jobs declared at the top
|
||||
val jobObject = it.toJobObject()
|
||||
jobsList.add(jobObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//loop through the jobs collected
|
||||
jobsList.forEach{
|
||||
//open the URl
|
||||
driver.get(it.url)
|
||||
|
||||
val title = driver.findElementByXPath("//*[@id=\"content\"]/div/div[2]/article")
|
||||
wait.until(ExpectedConditions.elementToBeClickable(title))
|
||||
|
||||
//check for external apply element
|
||||
val applyExternal = driver.findElementsByCssSelector("span.external-app-caption")
|
||||
|
||||
//if external apply is empty then apply for job
|
||||
if (applyExternal.isNullOrEmpty()){
|
||||
|
||||
print(it.jobTitle + " ${it.url} \n" )
|
||||
|
||||
|
||||
//find apply button
|
||||
val applyNow = driver.findElementsByXPath("//*[@id=\"applyButtonSide\"]")
|
||||
|
||||
if (!applyNow.isNullOrEmpty()){
|
||||
|
||||
//click apply
|
||||
applyNow[1].click()
|
||||
|
||||
try{
|
||||
val successfulApplied = driver.findElementByXPath("//*[@id=\"content\"]/div/div[1]/a")
|
||||
wait.until(ExpectedConditions.visibilityOf(successfulApplied))
|
||||
}catch (e: Exception){
|
||||
println(it.jobId + " did not apply")
|
||||
println("\n" + e.toString() + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// //Open Chrome
|
||||
// System.setProperty("webdriver.chrome.driver","C:\\Selenium\\selenium-java-3.141.59\\chromedriver_win32\\chromedriver.exe" )
|
||||
// val driver = ChromeDriver()
|
||||
//
|
||||
// //open reed website login
|
||||
// driver.get("https://www.reed.co.uk/account/signin?returnUrl=%2F#&card=signin")
|
||||
// val wait = WebDriverWait(driver, 20)
|
||||
//
|
||||
// //wait for page to load
|
||||
// val lastElementToLoad = driver.findElementById("signin-button")
|
||||
// wait.until(ExpectedConditions.elementToBeClickable(lastElementToLoad))
|
||||
//
|
||||
// //insert credentials and sign in
|
||||
// driver.findElementByXPath("//*[@id=\"Credentials_Email\"]").sendKeys(REED_USERNAME)
|
||||
// driver.findElementByXPath("//*[@id=\"Credentials_Password\"]").sendKeys(REED_PASSWORD)
|
||||
// lastElementToLoad.click()
|
||||
//
|
||||
// //wait for page to load
|
||||
// val jobSearchEditText = driver.findElementByXPath("//*[@id=\"keywords\"]")
|
||||
// wait.until(ExpectedConditions.elementToBeClickable(jobSearchEditText))
|
||||
//
|
||||
//// //submit search
|
||||
// jobSearchEditText.sendKeys(REED_KEYWORDS)
|
||||
// driver.findElementByXPath("//*[@id=\"location\"]").sendKeys(REED_LOCATION)
|
||||
// driver.findElementByXPath("//*[@id=\"main-search\"]/div[1]/div[3]/button").click()
|
||||
//
|
||||
// //todo: change to wait
|
||||
// Thread.sleep(1500)
|
||||
//
|
||||
// val ad = driver.findElementByXPath("//*[@id=\"content\"]/div[1]/div[2]/h1")
|
||||
// wait.until(ExpectedConditions.elementToBeClickable(ad))
|
||||
//
|
||||
// //find number of pages
|
||||
// val text = driver.findElementByCssSelector("div.page-counter").text /* eg. 1 - 25 of 99 jobs */
|
||||
// print(text)
|
||||
// val count = text.toTotalCount()
|
||||
// val pages = count.getNumberOfPages()
|
||||
//
|
||||
// //loop through pages of search
|
||||
// for (i in 1..pages){
|
||||
//
|
||||
// //open page by number on search
|
||||
// //todo: change this url builder
|
||||
// driver.get("https://www.reed.co.uk/jobs/android-developer-jobs-in-kilburn-london?pageno=$i")
|
||||
// Thread.sleep(2500)
|
||||
//
|
||||
// //elements list of jobs on page
|
||||
// val list = driver.findElementsByCssSelector("div.col-sm-12.col-md-9.col-lg-10.details")
|
||||
//
|
||||
// //turn list into global list job object
|
||||
// list.forEach {
|
||||
// val badge = it.findElement(By.cssSelector("div.badge-container"))
|
||||
// //check if there is a badge element
|
||||
// if (badge.isDisplayed){
|
||||
// //see if applied is in badge
|
||||
// val applied = badge.findElements(By.cssSelector("span.label.label-applied"))
|
||||
// //if applied doesnt exist then add to global list of jobs
|
||||
// if (applied.isNullOrEmpty()){
|
||||
// val jobObject = it.toJobObject()
|
||||
// jobsList.add(jobObject)
|
||||
// }
|
||||
//
|
||||
// }else{
|
||||
// //no badge exists so add to list of jobs declared at the top
|
||||
// val jobObject = it.toJobObject()
|
||||
// jobsList.add(jobObject)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //loop through the jobs collected
|
||||
// jobsList.forEach{
|
||||
// //open the URl
|
||||
// driver.get(it.url)
|
||||
//
|
||||
// val title = driver.findElementByXPath("//*[@id=\"content\"]/div/div[2]/article")
|
||||
// wait.until(ExpectedConditions.elementToBeClickable(title))
|
||||
//
|
||||
// //check for external apply element
|
||||
// val applyExternal = driver.findElementsByCssSelector("span.external-app-caption")
|
||||
//
|
||||
// //if external apply is empty then apply for job
|
||||
// if (applyExternal.isNullOrEmpty()){
|
||||
//
|
||||
// print(it.jobTitle + " ${it.url} \n" )
|
||||
//
|
||||
//
|
||||
// //find apply button
|
||||
// val applyNow = driver.findElementsByXPath("//*[@id=\"applyButtonSide\"]")
|
||||
//
|
||||
// if (!applyNow.isNullOrEmpty()){
|
||||
//
|
||||
// //click apply
|
||||
// applyNow[1].click()
|
||||
//
|
||||
// try{
|
||||
// val successfulApplied = driver.findElementByXPath("//*[@id=\"content\"]/div/div[1]/a")
|
||||
// wait.until(ExpectedConditions.visibilityOf(successfulApplied))
|
||||
// }catch (e: Exception){
|
||||
// println(it.jobId + " did not apply")
|
||||
// println("\n" + e.toString() + "\n")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
80
src/main/java/ListToExcel.kt
Normal file
80
src/main/java/ListToExcel.kt
Normal file
@@ -0,0 +1,80 @@
|
||||
import api.network.responses.ReedJobObject
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook
|
||||
import java.awt.Desktop
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.time.LocalDate
|
||||
import kotlin.reflect.full.memberProperties
|
||||
|
||||
|
||||
fun List<ReedJobObject>.writeToOut(){
|
||||
try {
|
||||
val workbook = XSSFWorkbook()
|
||||
val sheet = workbook.createSheet("sheet1") // creating a blank sheet
|
||||
|
||||
val headerList = takeKClass<ReedJobObject>()
|
||||
val topRow = sheet.createRow(0)
|
||||
ReedJobObject::class.memberProperties.forEachIndexed { headerPos, item ->
|
||||
topRow.createCell(headerPos).setCellValue(headerList[headerPos])
|
||||
}
|
||||
|
||||
this.forEachIndexed { index, reedJobObject ->
|
||||
val row = sheet.createRow(index + 1)
|
||||
|
||||
ReedJobObject::class.memberProperties.forEachIndexed { headerPos, item ->
|
||||
row.createCell(headerPos).setCellValue(item.get(reedJobObject).toString())
|
||||
}
|
||||
}
|
||||
|
||||
val dateTime = LocalDate.now().toString()
|
||||
val file = File("E:\\Reed search output\\Jobs applied - ${dateTime}.xlsx")
|
||||
val out = FileOutputStream(file) // file name with path
|
||||
workbook.write(out)
|
||||
out.close()
|
||||
val desktop = Desktop.getDesktop()
|
||||
if (file.exists()) //checks file exists or not
|
||||
desktop.open(file) //opens the specified file
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
//inline fun <reified T : Any> List<T>.writeToExcel() {
|
||||
// try {
|
||||
// val workbook = XSSFWorkbook()
|
||||
// val sheet = workbook.createSheet("sheet1") // creating a blank sheet
|
||||
// var rownum = 0
|
||||
//
|
||||
// val headerList = takeKClass<T>()
|
||||
//
|
||||
//
|
||||
// for (user in this) {
|
||||
//
|
||||
// val row: Row = sheet.createRow(rownum++)
|
||||
// createList(user, row)
|
||||
// }
|
||||
// val out = FileOutputStream(File("NewFile.xlsx")) // file name with path
|
||||
// workbook.write(out)
|
||||
// out.close()
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
inline fun <reified T: Any> takeKClass(): List<String> {
|
||||
val reflection = T::class
|
||||
|
||||
return reflection.members.map { it.name }
|
||||
}
|
||||
|
||||
inline fun <reified T: Any> List<T>.getElements(): List<List<String>> {
|
||||
val reflection = T::class
|
||||
|
||||
return this.map {
|
||||
reflection.memberProperties.map { kProperty1 ->
|
||||
kProperty1.get(it).toString()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,72 +4,78 @@ import api.network.NetworkRequests
|
||||
import api.network.responses.ReedJobObject
|
||||
import org.openqa.selenium.JavascriptExecutor
|
||||
import org.openqa.selenium.chrome.ChromeDriver
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions
|
||||
import org.openqa.selenium.support.ui.WebDriverWait
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
|
||||
var jobsList = mutableListOf<JobObject>()
|
||||
var appliedJobsList = mutableListOf<ReedJobObject>()
|
||||
var reedJobsList = listOf<ReedJobObject>()
|
||||
lateinit var driver: ChromeDriver
|
||||
lateinit var wait: WebDriverWait
|
||||
|
||||
const val driverPath = "C:\\Selenium\\selenium-java-3.141.59\\chromedriver_win32\\chromedriver.exe"
|
||||
public fun main(args: Array<String>){
|
||||
setup()
|
||||
getJobsFromReedApi()
|
||||
setupWebDriver()
|
||||
logonToReed()
|
||||
applyForJobsThroughLoop()
|
||||
applyForJobsThroughLoop {
|
||||
appliedJobsList.writeToOut()
|
||||
driver.close()
|
||||
exitProcess(2)
|
||||
}
|
||||
}
|
||||
|
||||
fun setup(){
|
||||
fun getJobsFromReedApi(){
|
||||
val result = NetworkRequests().getSearchApi()
|
||||
|
||||
if (!result.isNullOrEmpty()){
|
||||
reedJobsList = result
|
||||
result?.let {
|
||||
reedJobsList = it
|
||||
return
|
||||
}
|
||||
|
||||
// No results found so exit
|
||||
exitProcess(2)
|
||||
}
|
||||
|
||||
fun setupWebDriver(){
|
||||
//Open Chrome
|
||||
System.setProperty("webdriver.chrome.driver","C:\\Selenium\\selenium-java-3.141.59\\chromedriver_win32\\chromedriver.exe" )
|
||||
System.setProperty("webdriver.chrome.driver", driverPath)
|
||||
driver = ChromeDriver()
|
||||
wait = WebDriverWait(driver, 20)
|
||||
}
|
||||
|
||||
fun applyForJobsThroughLoop(){
|
||||
|
||||
reedJobsList.forEach {
|
||||
try {
|
||||
driver.get(it.jobUrl)
|
||||
applyForJob(it)
|
||||
|
||||
}catch (e: Exception){
|
||||
println("\n" + e.toString() + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun logonToReed(){
|
||||
driver.get("https://www.reed.co.uk/account/signin?returnUrl=%2F#&card=signin")
|
||||
|
||||
//wait for page to load
|
||||
val lastElementToLoad = driver.findElementById("signin-button")
|
||||
wait.until(ExpectedConditions.elementToBeClickable(lastElementToLoad))
|
||||
waitForPageToLoad()
|
||||
|
||||
//insert credentials and sign in
|
||||
driver.findElementByXPath("//*[@id=\"Credentials_Email\"]").sendKeys(REED_USERNAME)
|
||||
driver.findElementByXPath("//*[@id=\"Credentials_Password\"]").sendKeys(REED_PASSWORD)
|
||||
lastElementToLoad.click()
|
||||
|
||||
//wait for page to load
|
||||
val jobSearchEditText = driver.findElementByXPath("//*[@id=\"keywords\"]")
|
||||
wait.until(ExpectedConditions.elementToBeClickable(jobSearchEditText))
|
||||
// Click login and wait for page to load
|
||||
driver.findElementById("signin-button").click()
|
||||
waitForPageToLoad()
|
||||
}
|
||||
|
||||
fun applyForJobsThroughLoop(
|
||||
complete: () -> Unit
|
||||
){
|
||||
reedJobsList.forEach {
|
||||
try {
|
||||
// load url
|
||||
driver.get(it.jobUrl)
|
||||
// load [age
|
||||
waitForPageToLoad()
|
||||
// apply for job
|
||||
applyForJob(it)
|
||||
}catch (e: Exception){
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
complete()
|
||||
}
|
||||
|
||||
fun applyForJob(jobObject: ReedJobObject){
|
||||
val appliedBefore = driver.findElementsByXPath("//*[@id=\"content\"]/div/div[2]/article/div/div[1]/div")
|
||||
|
||||
if (appliedBefore.isNullOrEmpty()){
|
||||
if (hasUserNotAppliedBefore()){
|
||||
println("${jobObject.jobId} has not been applied")
|
||||
//find apply button
|
||||
val applyNow = driver.findElementsByXPath("//*[@id=\"applyButtonSide\"]")
|
||||
@@ -78,22 +84,27 @@ fun applyForJob(jobObject: ReedJobObject){
|
||||
//click apply
|
||||
val index = if (applyNow.size > 1){ 1 }else{ 0 }
|
||||
applyNow[index].click()
|
||||
|
||||
try{
|
||||
// val successfulApplied = driver.findElementByCssSelector("div.alert.alert-success alert-borderless")
|
||||
wait.until{
|
||||
driver.executeScript("return document.readyState") == "complete"
|
||||
}
|
||||
|
||||
}catch (e: Exception){
|
||||
println("\n" + e.toString() + "\n")
|
||||
}
|
||||
waitForPageToLoad()
|
||||
println("${jobObject.jobId} has now been applied for")
|
||||
appliedJobsList.add(jobObject)
|
||||
return
|
||||
}
|
||||
println("${jobObject.jobId} could not be applied for")
|
||||
}else{
|
||||
println("${jobObject.jobId} has been applied")
|
||||
println("${jobObject.jobId} has been applied for previously")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Checks to see if user has applied before
|
||||
fun hasUserNotAppliedBefore(): Boolean{
|
||||
// find "applied before" text
|
||||
val appliedBefore = driver.findElementsByXPath("//*[@id=\"content\"]/div/div[2]/article/div/div[1]/div")
|
||||
return appliedBefore.isNullOrEmpty()
|
||||
}
|
||||
|
||||
fun waitForPageToLoad(){
|
||||
//wait for page to load
|
||||
wait.until{driv ->
|
||||
(driv as JavascriptExecutor).executeScript("return document.readyState") == "complete"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
package api.network
|
||||
|
||||
import Constants.Companion.REED_KEYWORDS
|
||||
import Constants.Companion.REED_LOCATION
|
||||
import Constants.Companion.REED_MINIMUM_SALARY
|
||||
import api.network.responses.ReedJobObject
|
||||
import com.example.h_mal.androiddevelopertechtest_incrowdsports.data.network.ReedApi
|
||||
import com.example.h_mal.androiddevelopertechtest_incrowdsports.data.network.SafeApiRequest
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
class NetworkRequests : SafeApiRequest(){
|
||||
|
||||
val reedApi = ReedApi()
|
||||
val reedApi by lazy { ReedApi() }
|
||||
|
||||
fun getSearchApi() : List<ReedJobObject>?{
|
||||
try {
|
||||
val response = runBlocking { apiRequest { reedApi.getGameData(REED_KEYWORDS, REED_LOCATION, REED_MINIMUM_SALARY) } }
|
||||
// get results from Api
|
||||
val response = runBlocking {
|
||||
apiRequest { reedApi.getReedData(REED_KEYWORDS, REED_MINIMUM_SALARY) }
|
||||
}
|
||||
|
||||
// check we have results
|
||||
response.results?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
}catch (e : Exception){
|
||||
println("*** $e")
|
||||
e.printStackTrace()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -14,12 +14,22 @@ import retrofit2.http.Query
|
||||
|
||||
interface ReedApi {
|
||||
|
||||
//get the game data from api call of relevent gameID
|
||||
//get the job data from api call to Reed api data service
|
||||
@GET("search")
|
||||
suspend fun getGameData(@Query("keywords") keywords: String,
|
||||
suspend fun getReedData(@Query("keywords") keywords: String,
|
||||
@Query("minimumSalary") minimumSalary: String) : Response<ReedResponse>
|
||||
|
||||
@GET("search")
|
||||
suspend fun getReedData(@Query("keywords") keywords: String,
|
||||
@Query("locationName") locationName: String,
|
||||
@Query("minimumSalary") minimumSalary: String) : Response<ReedResponse>
|
||||
|
||||
@GET("search")
|
||||
suspend fun getReedData(@Query("keywords") keywords: String,
|
||||
@Query("locationName") locationName: String,
|
||||
@Query("minimumSalary") minimumSalary: String,
|
||||
@Query("resultsToSkip") resultToSkip: Int) : Response<ReedResponse>
|
||||
|
||||
//instantiate api class
|
||||
companion object{
|
||||
operator fun invoke() : ReedApi{
|
||||
|
||||
Reference in New Issue
Block a user