(Spring) 취향 기반 향수 추천 서비스 - 1. 데이터 크롤링

김준석·2023년 3월 16일
0

향수 추천 서비스

목록 보기
2/21

목표

향수 사이트에서 향수 정보 (이미지, 브랜드, 향수 이름, 특징)을 크롤링하여 CSV파일에 저장시킨다. 이후 CSV파일을 데이터베이스에 저장한다.

개발 기간

  • 2023/01/13~2023/01/14

전체 코드는 깃허브에 있다.

크롤링

  • CrawlingService.java

    private static final String PERFUME_NAME_CSS_QUERY_RANGE = "section.thumbnail a img";
    private static final String PERFUME_NAME_ATTRIBUTE_KEY = "alt";
    private static final String PERFUME_FEATURE_CSS_QUERY_RANGE = "ul.spec li.summary";
    private static final String IMG_URL = "src";

}

먼저 상수로 타겟들을 나눠줬다. 크롤링은 처음 해보는 일이었고, Java에도 해당 라이브러리가 존재하는지 몰라서 공부하면서 했다.

    public Document connectAndGetDocument(String targetUrl) throws IOException {
        Connection connection = Jsoup.connect(targetUrl);
        Document document = connection.get();

        return document;
    }

Jsoup라는 크롤링 라이브러리를 다운받아 사용했다.
targetUrl와 Connection한 후 Document 객체를 반환했다.


    public List<PerfumeCrawling> crawPerfumeName(String targetUrl) throws IOException {
        Elements setRange = connectAndGetDocument(targetUrl).select(PERFUME_NAME_CSS_QUERY_RANGE);
        List<PerfumeCrawling> perfumeCrawlingNameList = new ArrayList<>();
        for (int firstIndexOfList = LOOP_ZERO; firstIndexOfList < setRange.size(); firstIndexOfList++) {
            PerfumeCrawling perfumeCrawling = new PerfumeCrawling(setRange.get(firstIndexOfList).attr(PERFUME_NAME_ATTRIBUTE_KEY));
            perfumeCrawlingNameList.add(perfumeCrawling);
        }

        return perfumeCrawlingNameList;
    }

향수 이름을 크롤링해오는 메서드이다.
targetUrl에 범위를 설정해주는 setRange를 선언한 후, Loop로 모든 향수 데이터를 List에 담아서 반환하였다.

특징과 이미지도 동일한 방식으로 크롤링했다.

크롤링 한 데이터 CSV파일로 변환

  • CsvFileConversion.java
 private static final String filePath = "C:/Users/wnstj/perfume/젠더리스.csv";


    private File importedFile;
    private BufferedWriter bufferedWriter;


    public CsvFileConversion() throws IOException {
        this.importedFile = new File(filePath);
        this.bufferedWriter = new BufferedWriter(new FileWriter(importedFile));
    }

filePath를 지정해준 후, File과 BufferWriter을 필드로 선언해주었다.

    public String getCrawlingTarget(CrawlingService crawlingService, String targetUrl, int i) throws IOException {
        return crawlingService.crawPerfumeName(targetUrl).get(i)
                + "," + crawlingService.crawPerfumeFeature(targetUrl).get(i)
                + "," + crawlingService.crawPerfumeImageUrl(targetUrl).get(i);
    }

    public void makeCsvData(CrawlingService crawlingService, String targetUrl) throws IOException {
        int listSize = crawlingService.crawPerfumeFeature(targetUrl).size();

        for (int i = 0; i < listSize; i++) {
            String crawledData = "";
            crawledData = getCrawlingTarget(crawlingService, targetUrl, i);
            bufferedWriter.write(crawledData);
            bufferedWriter.newLine();
        }
        bufferedWriter.flush();

    }

csv파일은 ,단위로 열이 구분되기 때문에 ","단위를 나누어주었고, 이를 loop문으로 buffer.write를 하였다.

CSV파일을 DB에 저장

PerfumeCsvFileLoading.java

    public String[] splitData(String data) {
        return data.split(",");
    }

아까 열단위로 나누었었다.
열별로 다시 데이터를 수집해와야하기 때문에 ","단위로 split해주었다.

향수 데이터 저장

  • PerfumeService.java

public void savePerfumeData(Long id, PerfumeList perfume) throws IOException {
        perfume = perfumeCsvFileLoading.extractAllPerfumeData(perfume);
        for (int firstIndex = 0; firstIndex < perfume.getMaxSize(); firstIndex++) {
            Perfume perfumeDataSet = makePerfumeList(id, firstIndex, perfume).toEntity();
            perfumeRepository.save(perfumeDataSet);
        }
    }

앞에서 추출한 데이터들을 perfumeRepository에 저장하는 메서드이다.

다시 보니까...

코드를 많이 비효율적으로 짠 것 같다. 불과 두달 전에 개발한 것인데, 한눈에 보기 어려웠다.
크롤링하는 부분은 빠르게 개발을 마치고 메인 기능 구현으로 넘어가야 했기 때문에, 리팩토링을 거치지 않고 빠르게 개발을 했다. 나중에 졸업작품 끝나면 하나하나 리팩토링 해봐야겠다.

전체 코드

향수추천서비스

profile
기록하면서 성장하기!

0개의 댓글