프로그래밍

[자바] 올리브영 판매 랭킹 크롤링 본문

프로젝트

[자바] 올리브영 판매 랭킹 크롤링

시케 2023. 6. 4. 00:48
728x90
반응형

올리브영 웹페이지 크롤링

https://www.oliveyoung.co.kr/store/main/getBestList.do

 

랭킹 | 올리브영

대한민국 NO.1 헬스&뷰티 스토어 OLIVEYOUNG

www.oliveyoung.co.kr

해당 웹페이지의 코드를 분석하여 상품의 이름, 현재 판매가, 예전 판매가를 가져오고

데이터 처리까지 진행해 보겠다

 

페이지 분석

F12(개발자모드)를 작동시키면 해당 요소의 태그를 손쉽게 볼 수 있다

먼저 이름 정보는 "p.tx_name"에 있는 것을 볼 수 있다

 

해당 태그 요소

<p class="tx_name">[2천만국민크림/1+1기획] 닥터지 레드블레미쉬 클리어 수딩 크림 70ml 1+1 기획(파우치 랜덤증정)</p>

 

해당 태그 셀렉터

#Container > div.best-area > div.TabsConts.on > ul:nth-child(1) > li.flag > div > div > a > p

(우린 p태그 중 클래스명이 "tx_name"인 것이 필요)

 

기존 가격 정보는 p태그의 클래스명이 "prd_price"인 태그에 포함되어 있는 span태그의 클래스명이 "tx_org"인 곳에 또 span태그의 클래스명이 "tx_num"인 곳에 있다

 

즉, 다음과 같다

p.prd_price > span.tx_org > span.tx_num

 

해당 태그의 요소

<span class="tx_num">38,000</span>

 

해당 태그의 셀렉터

#Container > div.best-area > div.TabsConts.on > ul:nth-child(1) > li.flag > div > p.prd_price > span.tx_org > span

 

현재 가격 정보는 기존 가격 정보와 같지만 한단계 밑에 있다고 보면 된다

 

즉, 다음과 같다

p.prd_price > span.tx_cur > span.tx_num

 

해당 태그의 요소

<span class="tx_num">28,800</span>

 

해당 태그의 셀렉터

#Container > div.best-area > div.TabsConts.on > ul:nth-child(1) > li.flag > div > p.prd_price > span.tx_cur > span

 

이제 필요한 정보를 얻었으니 크롤링을 할 수 있다

 

예전 크롤링 예제

2023.05.31 - [자바 기초] - [자바 기초] day20 : 자바로 크롤링

 

[자바 기초] day20 : 자바로 크롤링

2023.05.31.수 웹 크롤링 웹 상의 코드를 분석하여 데이터를 가공하고 문서화하는 것을 말한다 스크랩핑 인터넷상에 존재하는 데이터를 프로그램을 이용하여 자동화된 방법으로 수집하는 작업 유

dev-9rm.tistory.com

 

이렇게 크롤링을 하면 오류가 난다

그 이유는 기존 가격이 없는 경우가 있기 때문이다

 

2023.06.03 - [자바 오류] - java.util.NoSuchElementException

 

java.util.NoSuchElementException

Exception in thread "main" java.util.NoSuchElementException at java.base/java.util.ArrayList$Itr.next(ArrayList.java:970) at model.Crawling.sample(Crawling.java:49) at model.ProductDAO.(ProductDAO.java:10) at ctrl.Ctrl.(Ctrl.java:19) at client.Client.main(

dev-9rm.tistory.com

 

요소들의 짝이 안 맞아 올바른 데이터를 취할 수 없다

 

어쩔 수 없이

현재 가격 정보와 기존 가격 정보가 같이 있는 "p.prd_price"를 한번에 가져와 데이터를 정제하기로 하였다

Elements elems = doc.select("p.tx_name");
Elements elems2 = doc.select("p.prd_price > span.tx_cur > span.tx_num");
Elements elems3 = doc.select("p.prd_price");


Iterator<Element> itr = elems.iterator();
Iterator<Element> itr2 = elems2.iterator();
Iterator<Element> itr3 = elems3.iterator();

 

각각 이름, 현재가격, 현재가격과 기존가격을 가져온다

 

while (itr.hasNext()) {
	String str = itr.next().text();
	String str2 = itr2.next().text();
	String str3 = itr3.next().text();

	str2 = str2.replaceAll("[^0-9]", "");
	str3 = str3.replaceAll("[^0-9]", "");
    
	if(str3.equals(str2)) {
		str3 = "-1";
	}
	else {
		str3 = str3.replace(str2, "");		
	}

Jsoup의 .text() 를 이용하면 태그안의 텍스트만 가져올 수 있다

 

이터레이터로 하나씩 꺼낸다(가져온 크기만큼 반복)

이름은 그냥 저장한다

현재가격, 현재가격과 기존가격 데이터에서 숫자가 아닌 문자열을 제거한다

만약 현재 가격만 있는 경우에는 "-1"원으로 설정한다

두 가격이 모두 존재하는 경우에는 중복되는 현재가격 데이터를 제거하여 각각 따로 저장한다

 

int price1 = Integer.parseInt(str2);
int price2 = Integer.parseInt(str3);
			

if(price2<0) {
	price2 = 0;
}
else {
	// 할인률: 100-((원가격/할인가)*100)
	double tmp = 100-((price1*1.0/price2*1.0)*100.0);
	price2 = (int) tmp;
}

원하는 데이터는 기존 가격이 아닌 할인률이므로 연산을 통해 구해서 저장한다

 

2023.06.03 - [자바 오류] - java.lang.NumberFormatException

 

java.lang.NumberFormatException

Exception in thread "main" java.lang.NumberFormatException: For input string: "3800028800" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67) at java.base/java.lang.Integer.parseInt(Integer.java:665) at java.base/jav

dev-9rm.tistory.com

 

전체 코드

package model;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Test01 {

	public static void main(String[] args) {
    
		final String url = "https://www.oliveyoung.co.kr/store/main/getBestList.do";

		Connection conn = Jsoup.connect(url);
		Document doc = null;
        
		try {
			doc = conn.get();
		} catch (IOException e) {
			e.printStackTrace();
		}

		Elements elems = doc.select("p.tx_name");
		Elements elems2 = doc.select("p.prd_price > span.tx_cur > span.tx_num");
		Elements elems3 = doc.select("p.prd_price");

		Iterator<Element> itr = elems.iterator();
		Iterator<Element> itr2 = elems2.iterator();
		Iterator<Element> itr3 = elems3.iterator();

		//////////////////////////////
		ArrayList<ProductVO> mdatas = new ArrayList<ProductVO>();
		int PK = 1001;
		//////////////////////////////

		while (itr.hasNext()) {
			String str = itr.next().text();
			String str2 = itr2.next().text();
			String str3 = itr3.next().text();

			str2 = str2.replaceAll("[^0-9]", "");
			str3 = str3.replaceAll("[^0-9]", "");

			if(str3.equals(str2)) {
				str3 = "-1";
			}
			else {
				str3 = str3.replace(str2, "");		
			}

			int price1 = Integer.parseInt(str2);
			int price2 = Integer.parseInt(str3);

			if(price2<0) {
				price2 = 0;
			}
			else {
				// 할인률: 100-((원가격/할인가)*100)
				double tmp = 100-((price1*1.0/price2*1.0)*100.0);
				price2 = (int) tmp;
			}

			System.out.println(price2);
			mdatas.add(new ProductVO(PK++, str, price1, price2));
		}

	}

}

 

다음에는 해당 데이터를 이용하여 간단한 프로그램을 만들어보겠다

728x90
반응형
Comments