스크래퍼 만들기

홍성진·2023년 6월 30일
0

Github 바로가기


crawler라고 코딩했지만, 일정한 페이지의 데이터만을 주기적으로 가져오기 때문에 scraper가 더 적합한 단어인 것 같습니다.

웹페이지의 요소를 가져오기 위해 Jsoup 을 사용했습니다.

needToSendFailMessagePatchNotesStorage의 존재 이유는 초기 개발을 완료 후에 발견한 두 가지 문제점들 때문입니다.

 


1. 서버 오류, 인터넷 연결실패 등의 이유로 웹페이지 요소를 가져오는 데 실패할 수 있음

// exception이 날 수 있다.
Document doc = Jsoup.connect(url).get();

이 경우 정상적인 스크래핑에 실패하므로 디스코드 채널에 연결상태를 전송해야 합니다. connected가 성공이 상태에서 연결에 실패한 경우 needToSendFailMessagetrue로 만들어 채널에 실패 메시지를 전송하도록 합니다.

 

2. 홈페이지 업데이트 중 업데이트 안내 페이지가 전달됨

// patchNoteElement로 empty한 객체가 return된다.
Elements patchNoteElements = doc.select("strong.title");

페이지 구조가 달라졌는데 기존 스크래핑 방식을 그대로 적용하면 아무것도 리턴되지 않기 때문에 비교대상 패치노트를 갱신하지 않도록 처리해야 합니다. 이를 쉽게 관리하기 위해 PatchNotesStorage 객체를 만들어 이전 패치노트와 현재 패치노트를 저장하도록 합니다.

 

package bnbnac.discordBot;

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.HashSet;
import java.util.Set;

import static bnbnac.discordBot.PatchNotesUtils.parseElementToPatchNote;

public class MyCrawler implements Crawler {
    private boolean connected;
    private PatchNotesStorage patchNotesStorage;

    public MyCrawler(PatchNotesStorage patchNotesStorage) {
        this.patchNotesStorage = patchNotesStorage;
        connected = true;
    }

    @Override
    public boolean crawl() {
        String url = "https://www.kr.playblackdesert.com/ko-kr/News/Notice?boardType=2";
        boolean needToSendFailMessage = false;

        try {
            Document doc = Jsoup.connect(url).get();
            connected = true;

            Elements patchNoteElements = doc.select("strong.title");

            Set<PatchNote> curPatchNotes = new HashSet<>();
            for (Element patchNoteElement : patchNoteElements) {
                curPatchNotes.add(parseElementToPatchNote(patchNoteElement));
            }

            patchNotesStorage.pushPatchNotes(curPatchNotes);
        } catch (IOException e) {
            e.printStackTrace();
            if (connected) {
                needToSendFailMessage = true;
            }
            connected = false;
        }

        return needToSendFailMessage;
    }
}

 


실제로 검은사막 공식홈페이지는 평소 이런 모습에서

홈페이지 업데이트 중일 때는 이런 페이지를 보내줍니다.

참고 링크

JDA
디스코드 개발자 페이지
Jsoup
검은사막

0개의 댓글