Skip to content

Commit

Permalink
Merge pull request #30 from giwoong01/develop
Browse files Browse the repository at this point in the history
feat:Crawling 구현
  • Loading branch information
giwoong01 authored Oct 24, 2023
2 parents 0907e53 + 7ed8e32 commit 5f2f727
Show file tree
Hide file tree
Showing 14 changed files with 398 additions and 289 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ dependencies {
implementation 'io.springfox:springfox-boot-starter:3.0.0'
implementation 'io.springfox:springfox-swagger-ui:3.0.0'

// Jsoup
implementation 'org.jsoup:jsoup:1.15.3'

// intelliJ에서 db사용
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,19 @@ public class NoticeSaveReqDto {

private String title;

private String schedule;

private String contents;

private int mileageScore;

private String createDate;

private String author;

private String links;

public NoticeSaveReqDto(String title, String schedule, String contents, int mileageScore, String createDate, String links) {
public NoticeSaveReqDto(String title, String contents, String createDate, String author, String links) {
this.title = title;
this.schedule = schedule;
this.contents = contents;
this.mileageScore = mileageScore;
this.createDate = createDate;
this.author = author;
this.links = links;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ public AdminService(NoticeRepository noticeRepository, MemberScrapNoticeReposito

// 공지 등록
public void noticeSave(NoticeSaveReqDto noticeSaveReqDto) {
Notice notice = new Notice(noticeSaveReqDto.getTitle(),
noticeSaveReqDto.getSchedule(),
Notice notice = new Notice(
noticeSaveReqDto.getTitle(),
noticeSaveReqDto.getContents(),
noticeSaveReqDto.getMileageScore(),
noticeSaveReqDto.getCreateDate(),
noticeSaveReqDto.getAuthor(),
true,
noticeSaveReqDto.getLinks());

noticeRepository.save(notice);
Expand All @@ -39,12 +40,13 @@ public void noticeSave(NoticeSaveReqDto noticeSaveReqDto) {
public void noticeUpdate(Long noticeId, NoticeSaveReqDto noticeSaveReqDto) {
Notice notice = noticeRepository.findById(noticeId).orElseThrow(NotFoundNoticeException::new);

notice.update(noticeSaveReqDto.getTitle(),
noticeSaveReqDto.getSchedule(),
notice.update(
noticeSaveReqDto.getTitle(),
noticeSaveReqDto.getContents(),
noticeSaveReqDto.getMileageScore(),
noticeSaveReqDto.getCreateDate(),
noticeSaveReqDto.getLinks());
noticeSaveReqDto.getLinks(),
true,
noticeSaveReqDto.getAuthor());
}

// 공지 삭제
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.itcontest.skhuming.mileage.exception.NotAddMileageException;
import com.itcontest.skhuming.mileage.exception.NotFoundMileageException;
import com.itcontest.skhuming.notice.exception.NotFoundNoticeException;
import com.itcontest.skhuming.notice.exception.NotScheduleFormatException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
Expand All @@ -25,7 +24,6 @@ public class ControllerAdvice {
NotFoundMemberException.class,
NotFoundNoticeException.class,
NotFoundMileageException.class,
NotScheduleFormatException.class,
NotFoundDepartmentException.class,
NotMatchTokenException.class,
NotAddMileageException.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.itcontest.skhuming.notice.api;

import com.itcontest.skhuming.notice.application.CrawlingService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

@RestController
public class CrawlingController {
private final CrawlingService crawlingService;

public CrawlingController(CrawlingService crawlingService) {
this.crawlingService = crawlingService;
}

@PostMapping("/api/admin/get-crawling")
public ResponseEntity<String> crawlingSuccess() throws IOException {
crawlingService.getNoticeData();
return new ResponseEntity<>("SUCCESS", HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,23 @@ public class DetailsNoticeResDto {

private String title;

private String schedule;

private String contents;

private int mileageScore;

private String createDate;

private String links;

private String author;

private List<Long> memberId = new ArrayList<>();

public DetailsNoticeResDto(Long noticeId, String title, String schedule, String contents, int mileageScore, String createDate, String links, List<Long> memberId) {
public DetailsNoticeResDto(Long noticeId, String title, String contents, String createDate, String links, String author, List<Long> memberId) {
this.noticeId = noticeId;
this.title = title;
this.schedule = schedule;
this.contents = contents;
this.mileageScore = mileageScore;
this.createDate = createDate;
this.links = links;
this.author = author;
this.memberId = memberId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ public class NoticeListResDto {
private Long noticeId;
private String title;
private String createDate;
private boolean end;
private boolean status;

public NoticeListResDto(Long noticeId, String title, String createDate, boolean end) {
public NoticeListResDto(Long noticeId, String title, String createDate, boolean status) {
this.noticeId = noticeId;
this.title = title;
this.createDate = createDate;
this.end = end;
this.status = status;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.itcontest.skhuming.notice.application;

import com.itcontest.skhuming.notice.domain.Notice;
import com.itcontest.skhuming.notice.domain.repository.NoticeRepository;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Transactional(readOnly = true)
public class CrawlingService {
private final NoticeRepository noticeRepository;
private final String BASE_URL = "https://www.skhu.ac.kr";
private final String URL = BASE_URL + "/skhu/4198/subview.do";

public CrawlingService(NoticeRepository noticeRepository) {
this.noticeRepository = noticeRepository;
}

@Transactional
public void getNoticeData() throws IOException {
List<Notice> notices = new ArrayList<>();

Document document = Jsoup.connect(URL).get();

for (int page = 1; page <= 5; page++) {
Elements noticeElement = document.select("table.board-table.horizon1 tbody tr");

for (Element content : noticeElement) {
// 번호
String number = content.select("td.td-num").text();

// 일반 공지 (중요 공지) 제외
if (number.equals("일반공지")) {
continue;
}

// 상태
String status = content.select("td.td-state").text();
boolean statusBoolean = "진행중".equals(status); // true가 진행중

// 제목
String title = content.select("td.td-subject strong").text();

// 작성일
String writeDate = content.select("td.td-date").text();

// 작성자
String author = content.select("td.td-write").text();

// 공지사항 url
Element linkElement = content.select("a").first();
String relativeUrl = linkElement.attr("href");

// BASE_URL(기본 https) + relativeUrl
String fullUrl = BASE_URL + relativeUrl;

// 상세 공지 내용
StringBuilder contents = new StringBuilder();
Document detailDocument = Jsoup.connect(fullUrl).get();
Elements contentElements = detailDocument.select("._fnctWrap .view-con");

// <p>태그로 구분하여 줄바꿈
for (Element element : contentElements.select("p")) {
contents.append(element.text()).append("\n");
}

for (Element element : contentElements.select("h3")) {
contents.append(element.text()).append("\n");
}

Notice notice = new Notice(
title,
contents.toString(),
writeDate,
fullUrl,
statusBoolean,
author);

if (!contents.toString().trim().isEmpty() && !noticeRepository.existsByTitleAndContents(title, contents.toString())) {
notices.add(notice);
}
}
// 다음 페이지로 이동하기 위해 URL 변경
if (page < 5) {
String nextPageUrl = BASE_URL + "/skhu/4198/subview.do?page=" + (page + 1);
document = Jsoup.connect(nextPageUrl).get();
}
}

if (!notices.isEmpty()) {
noticeRepository.saveAll(notices);
}
}
}
Loading

0 comments on commit 5f2f727

Please sign in to comment.