카테고리 없음

6. 사람인에서 모든 채용페이지를 크롤링할 수 있게 함

patrick-star 2022. 8. 21. 22:30
728x90

결과

위 이미지에 포함되지 않았지만 카카오를 검색했을 때 나오는 2000 여개의 결과를 모두 크롤링했다.

코드

사람인 사이트에서 크롤링하는 코드를 아래와 같이 수정했다.

1) 페이지 번호를 옮기기 위해서 recruitPage 파라미터를 추가했다. 반복이 시작될 때 마다 페이지 번호를 1씩 증가시킨다.

2) 크롤링을 위해서 By.cssSelector() 메소드를 사용했다. 이 메소드를 사용하면 원하는 html의 구조에 따라서 크롤링할 수 있기 때문이다.

package org.example.springboot.web.recruiteWebSite;

import java.io.IOException;
import java.util.List;
import java.util.LinkedList;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class SaramIn {

    // 파라미터 str = 검색 url
    // 일단, 채용정보 1페이지에 있는 내용만 출력하도록 하자.
    // 채용정보 파라미터는 recruitPage. company 뒤에 &로 이어서 전달하면 된다.
    // ex) 2페이지 - recruitPage = 2
    public static String saramInSearch(String str) throws IOException {

        String result = "";

        WebDriver driver;

        final String WEB_DRIVER_ID = "webdriver.chrome.driver";
        final String WEB_DRIVER_PATH = "C:/devtool/chromedriver_win32/chromedriver.exe"; // 크롬 드라이버 경로

        String base_url; // 크롤링 할 url

        // System Property 설정
        System.setProperty(WEB_DRIVER_ID, WEB_DRIVER_PATH);

        driver = new ChromeDriver();
        base_url = str + "&recruitPage="; // 페이지 번호 매개변수를 추가한 url

        List<WebElement> titleList = new LinkedList<WebElement>();
        List<WebElement> companyList = new LinkedList<WebElement>();

        try {
            int pageNumber = 1;

            int prevCount = 0;
            while(true) {

                // 반복문이 돌아올 때 마다 페이지 번호를 1씩 증가시킨다.
                driver.get(base_url + Integer.toString(pageNumber++));

                // item_recruit라는 이름의 클래스 리스트를 불러옴

                // <div id = "recruit_info_list"> -> <div class = "content">
                // -> <div class = "item_recruit"> -> <div class = "area_job"> -> <h2 class = "job_tit">
                titleList = driver.findElements(
                        By.cssSelector("#recruit_info_list > div.content > div.item_recruit > div.area_job > h2.job_tit"));

                companyList = driver.findElements(
                        By.cssSelector("#recruit_info_list > div.content > div.item_recruit > div.area_corp > strong.corp_name"));

                // 더 이상 검색결과가 없을 때까지 반복한다.
                if(titleList.size() == 0) break;

                try {
                    for(int i = 0; i < titleList.size(); i++) {

                        // mustache 파일에서 {}를 3개 쓰면 <br>과 같은 html 기능을 적용할 수 있다.
                        result += "채용 공고 = " + titleList.get(i).getText()
                                + " "
                                + " 회사 = " + companyList.get(i).getText() + "<br>";

                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        driver.close();

        return result;
    }
}

보완할 점

1) 오류 가 발생했다. 이 오류가 정확히 왜 발생했는지는 알 수 없지만 오류가 발생한 상황을 아래에 적어놓으려 한다. 정상적으로 동작한 상황은 위에 제시한 코드다.

알아냈다면 반드시 그 이유를 여기에 남겨놓자.

  • 오류 상황
package org.example.springboot.web.recruiteWebSite;

import java.io.IOException;
import java.util.List;
import java.util.LinkedList;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;


public class SaramIn {

    // 파라미터 str = 검색 url
    // 일단, 채용정보 1페이지에 있는 내용만 출력하도록 하자.
    // 채용정보 파라미터는 recruitPage. company 뒤에 &로 이어서 전달하면 된다.
    // ex) 2페이지 - recruitPage = 2
    public static String saramInSearch(String str) throws IOException {

        String result = "";

        WebDriver driver;

        final String WEB_DRIVER_ID = "webdriver.chrome.driver";
        final String WEB_DRIVER_PATH = "C:/devtool/chromedriver_win32/chromedriver.exe"; // 크롬 드라이버 경로

        String base_url; // 크롤링 할 url

        // System Property 설정
        System.setProperty(WEB_DRIVER_ID, WEB_DRIVER_PATH);

        driver = new ChromeDriver();
        base_url = str + "&recruitPage="; // 페이지 번호 매개변수를 추가한 url

        List<WebElement> titleList = new LinkedList<WebElement>();
        List<WebElement> companyList = new LinkedList<WebElement>();

        try {
            int pageNumber = 1;

            int prevCount = 0; // titleList가 이전에 가지고 있던 자료 크기
            while(true) {
                //get page (= 브라우저에서 url을 주소창에 넣은 후 request 한 것과 같다)

                driver.get(base_url + Integer.toString(pageNumber++));

                // item_recruit라는 이름의 클래스 리스트를 불러옴

                // <div id = "recruit_info_list"> -> <div class = "content">
                // -> <div class = "item_recruit"> -> <div class = "area_job"> -> <h2 class = "job_tit">
                titleList.addAll(driver.findElements(
                         By.cssSelector("#recruit_info_list > div.content > div.item_recruit > div.area_job > h2 > a")));

                companyList.addAll(driver.findElements(
                         By.cssSelector("#recruit_info_list > div.content > div.item_recruit > div.area_corp > strong > a")));

                // 더 이상 검색결과가 없을 때까지 반복한다.
                // 이전 자료 크기와 현재 자료크기가 같다는 건 검색결과가 없다는 뜻
                if(prevCount == titleList.size()) break;

                prevCount = titleList.size();


            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        try {
            for(int i = 0; i < titleList.size(); i++) {


                // System.out.println(el1.get(i).getText());
                // {}를 3개 쓰면서 <br>을 추가해줌으로써 줄 바꿈이 가능해짐

                // 문제가 된 부분
                // stale element reference: element is not attached to the page document
                // 진짜 text를 읽을 수 없어서 생긴 문제 - https://heodolf.tistory.com/80 -
                result += "채용 공고 = " + titleList.get(i).getText()
                        + " "
                        + " 회사 = " + companyList.get(i).getText() + "<br>";

            }

        } catch (Exception e) {
            e.printStackTrace();
        }




        driver.close();

        return result;
    }
}

위 코드에서 문제가 된 부분을 아래와 같이 바꾼다면

result += "채용 공고 = " + titleList.get(i).
                        + " "
                        + " 회사 = " + companyList.get(i). + "<br>";

이런 결과가 나온다.

채용 공고 = [ChromeDriver: chrome on WINDOWS (a4f958a4c6c90b3b9be6163dd75a2f4f)] -> css selector: #recruit_info_list > div.content > div.item_recruit > div.area_job > h2 > a] 회사 = [ChromeDriver: chrome on WINDOWS (a4f958a4c6c90b3b9be6163dd75a2f4f)] -> css selector: #recruit_info_list > div.content > div.item_recruit > div.area_job > strong > a]