2018-7-31 크롤러 데이터처리

@Service
public class StockService {
    public static final Logger logger = LoggerFactory.getLogger(StockService.class);

    @Resource(name = "stockRepository")
    private StockRepository stockRepository;

    public List<Stock> findAll() {
        return stockRepository.findAll();
    }

    public Stock findById(long id) {
        return stockRepository.findOne(id);
    }

    public Stock findByName(String stockName) {
        logger.info("stockName on Service : {}", stockName);
        return stockRepository.findByName(stockName);
    }

    public Stock add(String stockName) throws Exception {
        Research research = new Research(stockName);
        return stockRepository.save(research.update(stockRepository.findByName(stockName.toUpperCase()), checkMakingStock(stockName)));
    }

    public boolean checkMakingStock(String stockName) {
        Stock stock = stockRepository.findByName(stockName.toUpperCase());
        if (stock != null && stock.getDiffday() < 15)
            return true;
        logger.info("stockName : {}", stockName);
        return false;
    }

    @Transactional
    public void delete(long id) throws Exception {
        logger.info("delete method called {}", id);
        stockRepository.delete(id);
    }
}

@Service
public class Research {
    public static final Logger logger = LoggerFactory.getLogger(Research.class);
    private WebDriver driver;
    private String stockName;
    private String price;
    private String changeMoney;
    private String changePercent;

    public Research() {}

    public Research(String stockName) {
        this.stockName = stockName.toUpperCase();
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless");
        System.setProperty("webdriver.chrome.driver", "/Users/jaeyeonkim/Desktop/web-crawler/src/main/java/com/example/demo/chromedriver");
        driver = new ChromeDriver(options);
        String startUrl = "http://finance.daum.net/";
        driver.get(startUrl);
    }


    public String search() {
        driver.findElement(By.id("name")).sendKeys(getStockName());
        driver.findElement(By.id("daumBtnSearch")).click();
        WebElement element = driver.findElement(By.cssSelector("a[title="+getStockName()+"]"));
        String detailUrl  = element.getAttribute("href");
        return detailUrl;
    }

    public Stock update(Stock original, boolean check) {
        driver.get(search());
        price = driver.findElement(By.xpath("//*[@id=\"topWrap\"]/div[1]/ul[2]/li[1]/em")).getText();
        changeMoney = driver.findElement(By.xpath("//*[@id=\"topWrap\"]/div[1]/ul[2]/li[2]/span")).getText();
        changePercent = driver.findElement(By.xpath("//*[@id=\"topWrap\"]/div[1]/ul[2]/li[3]/span")).getText();
        if (!check)
            return make();
        original.update(price, changeMoney, changePercent);
        logger.info("update info : {}", original.toString());
        return original;
    }

    public Stock make() {
        String salesMoney = driver.findElement(By.xpath("//*[@id=\"performanceCorp\"]/table/tbody/tr[4]/td[9]")).getText();
        String totalCost = driver.findElement(By.xpath("//*[@id=\"stockContent\"]/ul[2]/li[2]/dl[2]/dd")).getText();
        String yearProfit = driver.findElement(By.xpath("//*[@id=\"performanceCorp\"]/table/tbody/tr[5]/td[9]")).getText();
        return new Stock(getStockName(), getPrice(), salesMoney, yearProfit, totalCost, getChangeMoney(), getChangePercent(), search());
    }

    public String getPrice() {
        return price;
    }

    public String getChangeMoney() {
        return changeMoney;
    }

    public String getChangePercent() {
        return changePercent;
    }

    public String getStockName() {
        return stockName;
    }

}
  • 크롤러에서 주식에 관한 정보를 가지고 올때, 실시간가격 변동률 변동가격 등은 실시간으로 변하는 데이터이다. 하지만 영업이익 매출액과 같은 데이터는 변동이 거의없다.
  • 2개의 데이터로 나누었다. 변하는 데이터와 자주안변하는 데이터로 구분을 해서. 자주안변하는 데이터에 대해서는 데이터베이스에 값을 넣고 가지고 오는 형태로, 실시간으로 변하는 데이터는 크롤링을 하는 형태로 구분을 해서 Stock객체를 생성을 한다.
  • Stock객체는 CreateDate, ModifiedDate로 구분이되어서, 현재시각과 비교를 해서 업데이트 날짜와 현재날짜의 차이가 기준시간보다 클 경우 새로 업데이틀르 하고 그렇지 않은경우에는 실시간데이터만 가지고와서 처리를 한다.
Written on July 31, 2018