혼자 고민해보기_ 개발/TIL (Today I Learned)

20230831(목)_ 최종프로젝트 진행

nuri-story 2023. 9. 2. 00:39

금일 달성 항목

1)  인크루트로 크롤링하기


문제 해결 과정 1 - 인크루트 상세정보 가져오기

[문제]
잡코리아 크롤링을 실패하고 깔끔하게 다른 사이트로 크롤링을 시도해야하는 상황이었습니다.

 

[시도 및 해결]

처음부터 다시 생성하여서 코드를 작성하였는데, 자꾸만 crate와 insert에 담기지 않는 상황이었습니다.

 const companyEntities = [];
    companyInfo.forEach((company) => {
      const companyEntity = this.companyRepository.create({
        // 생성하고
        id: company.id,
        email: company.email,
        password: company.password,
        title: company.title,
        introduction: company.introduction,
        business: company.business,
        employees: company.employees,
        image: company.image,
        website: company.website,
        address: company.website,
      });
      companyEntities.push(companyEntity);

      console.log(
        "==============companyEntities================",
        companyEntities
      );
    });

튜터님께 여쭤보니 forEach 문과 map은 콜백함수로 비동기 함수를 받더라도 실행을 기다려주지 않기때문에 for 문으로 작성해보라고 하셨습니다.

 

https://constructionsite.tistory.com/43

 

[JS] forEach 함수는 async 함수를 기다려주지 않는다

최근 Mongoose를 사용하는 프로젝트를 진행하면서 forEach 함수는 비동기(async) 함수를 기다려주지 않는다는 걸 알게 되었다. forEach 함수의 콜백이 비동기 함수일 때 경험한 문제 문제가 생긴 코드는

constructionsite.tistory.com

또한 배열을 [] 초기화하므로 for문을 두번 돌려 생성해야하는 상황이었습니다.

 async inflearnCrawling() {
    console.time('코드 실행시간');
    // 코드 실행시간을 구해줌

    const totalPage = 1; // 크롤링할 갯수
    const jobInfo = [];
    const companyInfo = [];

    // 페이지수 만큼 반복문을 돌며 정보를 크롤링
    // 해당 페이지의 URL을 생성하고, 이를 getPuppeteerData통해 Puppeteer를 통해 가져오기를 사용
    for (let i = 1; i <= totalPage; i++) {
      const jobpostingUrl = `https://job.incruit.com/jobdb_list/searchjob.asp?ct=3&ty=1&cd=149&page=${i}`;
      const jobpostingContent = await this.getAxiosData(jobpostingUrl);

      // Cheerio를 사용하여 페이지의 HTML을 파싱하고, jobLinks선택하여 채용공고의 링크를 제공
      const $ = cheerio.load(jobpostingContent);
      const jobLinks = $('li.c_col .cell_mid .cl_top a');
      for (const jobLink of jobLinks) {
        // 채용공고의 링크를 순회해서 상세페이지의 HTML을 가져오고

        const jobDetailUrl = $(jobLink).attr('href');

        console.log('================jobLinks===============', jobDetailUrl);

        const companyContent = await this.getAxiosData(jobDetailUrl);

        const jobContent = await this.getAxiosData(jobDetailUrl);
        const companies = this.companyParsing(companyContent);
        const jobs = this.jobParsing(jobContent);
        companyInfo.push(companies);
        jobInfo.push(jobs);

        // [[company, company], [company, company], [company, company], []]

        await this.delay(10000); // 각페이지 크롤링 후 5초 대기
      }
    }
    // 코드 실행시간을 측정
    console.log('===========companyInfo===========', companyInfo);
    console.log('==========jobInfo================', jobInfo);

    // companyEntities에 담을 초기화 배열

    for (const companys of companyInfo) {
      for (const company of companys) {
        // const companyEntities = [];
        const companyEntity = this.companyRepository.create({
          // 생성하고
          id: company.id,
          email: company.email,
          password: company.password,
          title: company.title,
          introduction: company.introduction,
          business: company.business,
          employees: company.employees,
          image: company.image,
          website: company.website,
          address: company.address,
        });
        // companyEntities.push(companyEntity);
        const isExist = await this.companyRepository.findOne({
          where: { id: company.id },
        });
        if (!isExist) {
          await this.companyRepository.insert(companyEntity);
        }
      }
    }
    // console.log(
    //   '==============companyEntities================',
    //   companyEntities,
    // );

    // 회사 DB에 저장한다

    for (const jobs of jobInfo) {
      for (const job of jobs) {
        const jobEntity = this.jobpostingRepository.create({
          // 생성하고
          companyId: job.companyId,
          // company: { id: company.id },
          // companyId: company.id,
          title: job.title,
          career: job.career,
          salary: job.salary,
          education: job.education,
          workType: job.workType,
          workArea: job.workArea,
          content: job.content,
          dueDate: job.dueDate,
        });
        this.jobpostingRepository.insert(jobEntity); // 채용공고 DB에 저장한다
      }
    }

    // 리턴값 보여주기..
    return { jobInfo, companyInfo };
  }
  private delay(ms: number) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }
}

 

[알게된 점]

기초적인 문법을 많이 알아야겠다고 생각했습니다.