향수 사이트에서 향수 정보 (이미지, 브랜드, 향수 이름, 특징)을 크롤링하여 CSV파일에 저장시킨다. 이후 CSV파일을 데이터베이스에 저장한다.
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에 담아서 반환하였다.
특징과 이미지도 동일한 방식으로 크롤링했다.
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를 하였다.
PerfumeCsvFileLoading.java
public String[] splitData(String data) {
return data.split(",");
}
아까 열단위로 나누었었다.
열별로 다시 데이터를 수집해와야하기 때문에 ","단위로 split해주었다.
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에 저장하는 메서드이다.
코드를 많이 비효율적으로 짠 것 같다. 불과 두달 전에 개발한 것인데, 한눈에 보기 어려웠다.
크롤링하는 부분은 빠르게 개발을 마치고 메인 기능 구현으로 넘어가야 했기 때문에, 리팩토링을 거치지 않고 빠르게 개발을 했다. 나중에 졸업작품 끝나면 하나하나 리팩토링 해봐야겠다.