Skip to content

Commit

Permalink
[FEAT] 가톨릭대 도서관 열람실 인원 크롤러 개발
Browse files Browse the repository at this point in the history
  • Loading branch information
SolfE authored Oct 21, 2024
1 parent f23bae8 commit ba866bd
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 0 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.jsoup:jsoup:1.16.1'
implementation 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/catspot/CatspotApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class CatspotApplication {

public static void main(String[] args) {
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/com/catspot/crawler/CrawlerScheduler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.catspot.crawler;

import lombok.AllArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Component
@AllArgsConstructor
public class CrawlerScheduler {
private final StudyPlaceRepository studyPlaceRepository;

@Transactional
@Scheduled(fixedRate = 60000)
public void crawl() {
List<StudyPlace> places = LibraryCrawler.getData();
List<StudyPlace> studyPlacesToSave = new ArrayList<>();

for (StudyPlace place : places) {
StudyPlace studyPlace = studyPlaceRepository.findById(place.getPlaceIdx()).orElseGet(() -> place);

studyPlace.setPlaceName(place.getPlaceName());
studyPlace.setUrl(place.getUrl());
studyPlace.setAllSeats(place.getAllSeats());
studyPlace.setUseSeats(place.getUseSeats());
studyPlace.setRestSeats(place.getRestSeats());

studyPlacesToSave.add(studyPlace);
}

studyPlaceRepository.saveAll(studyPlacesToSave);
}
}
53 changes: 53 additions & 0 deletions src/main/java/com/catspot/crawler/LibraryCrawler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.catspot.crawler;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class LibraryCrawler {
private static final String baseUrl = "http://203.229.203.240/8080";
private static final String tableUrl = "/Domian5_jythh.asp";
private static final String seatUrl = "/roomview5.asp?room_no=";

public static List<StudyPlace> getData() {
List<StudyPlace> data = new ArrayList<>();
try {
Document table = Jsoup.connect(baseUrl + tableUrl).get();
Elements rows = table.select("tbody tr");

for (int i = 0; i < rows.size(); i ++) {
Element row = rows.get(i);
String name = row.select("a").text();
String url = baseUrl + seatUrl + (i + 1);

Document seat = Jsoup.connect(url).get();
Elements seatStatus = seat.select("td b");

Integer allSeats = Integer.parseInt(seatStatus.get(3).text());
Integer useSeats = Integer.parseInt(seatStatus.get(5).text());
Integer restSeats = Integer.parseInt(seatStatus.get(7).text());

StudyPlace studyPlace = StudyPlace.builder()
.placeIdx((long) i)
.placeName(name)
.url(url)
.allSeats(allSeats)
.useSeats(useSeats)
.restSeats(restSeats)
.build();

data.add(studyPlace);
}

if (data.isEmpty()) throw new IOException();
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
}
27 changes: 27 additions & 0 deletions src/main/java/com/catspot/crawler/StudyPlace.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.catspot.crawler;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import lombok.*;

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
public class StudyPlace {
@Id
private Long placeIdx;
private String placeName;
private String url;
private Integer allSeats;
private Integer useSeats;
private Integer restSeats;

@Override
public String toString() {
return "placeIdx=" + placeIdx + ", placeName=" + placeName + ", url=" + url +
", allSeats=" + allSeats + ", useSeats=" + useSeats + ", restSeats=" + restSeats;
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/catspot/crawler/StudyPlaceRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.catspot.crawler;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudyPlaceRepository extends JpaRepository<StudyPlace, Long> {
}
18 changes: 18 additions & 0 deletions src/test/java/com/catspot/crawler/LibraryCrawlerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.catspot.crawler;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.List;

class LibraryCrawlerTest {
@Test
void 크롤링_페이지_정상동작() {
// when
List<StudyPlace> data = LibraryCrawler.getData();

// then
System.out.println(data);
Assertions.assertFalse(data.isEmpty());
}
}
32 changes: 32 additions & 0 deletions src/test/java/com/catspot/crawler/StudyPlaceRepositoryTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.catspot.crawler;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

@DataJpaTest
class StudyPlaceRepositoryTest {

@Autowired
private StudyPlaceRepository studyPlaceRepository;

@Test
void 저장_후_인덱스를_통한_조회() {
StudyPlace studyPlace = StudyPlace.builder()
.placeIdx(1L)
.placeName("1")
.url("url")
.allSeats(10)
.useSeats(2)
.restSeats(8)
.build();
studyPlaceRepository.save(studyPlace);

StudyPlace foundStudyPlace = studyPlaceRepository.findById(1L).get();

Assertions.assertNotNull(foundStudyPlace);
Assertions.assertEquals(foundStudyPlace.getPlaceIdx(), 1);
Assertions.assertEquals(foundStudyPlace.getPlaceName(), "1");
}
}
20 changes: 20 additions & 0 deletions src/test/java/com/catspot/crawler/StudyPlaceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.catspot.crawler;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

class StudyPlaceTest {
@Test
void 열람실_엔티티_생성() {
StudyPlace studyPlace = StudyPlace.builder()
.placeIdx(1L)
.placeName("1")
.url("url")
.allSeats(10)
.useSeats(2)
.restSeats(8)
.build();

Assertions.assertEquals(studyPlace.getPlaceIdx(), 1);
}
}

0 comments on commit ba866bd

Please sign in to comment.