오래 못 할 짓 하지 않기

[ 혼자하는 웹 프로젝트 ] 4. 크롤링한 데이터 내 입맛에 맞게 쓰기 본문

혼자하기/웹 프로젝트 1) 뉴스

[ 혼자하는 웹 프로젝트 ] 4. 크롤링한 데이터 내 입맛에 맞게 쓰기

쫑알bot 2023. 8. 23. 17:41
728x90
  • 완성한 항목 :
    크롤링  + 원하는 데이터들 뽑아서 가져오기 + 10개만 출력하기
    ( + DB에 추가는 아직 못 했음 이따 할 예정 ) 
public void addContToDB(News news) throws  Exception{
    String URL = "https://www.yna.co.kr/economy/all?site=navi_economy_depth02";

    Document doc = Jsoup.connect(URL).get();
    Elements elem = doc.select("div[class=\"news-con\"]");


    int i=1;
    for(Element e:elem.select("div[class=\"news-con\"]")){
        System.out.print(i+" 제목: " + e.select("strong[class=\"tit-news\"]").text());
        System.out.println("   || 내용 : "+e.select("p[class=\"lead\"]").text());
        //e.text()를 DB에 넣기
        
        i++;
        //10개만 출력할 예정임
        if(i==11){
            break;
        }
    }



}

여기에서 for문 한 번 유심히 보자

 

for(Element e:elem.select("div[class=\"news-con\"]")){
    System.out.print(i+" 제목: " + e.select("strong[class=\"tit-news\"]").text());
    System.out.println("   || 내용 : "+e.select("p[class=\"lead\"]").text());

일단 지금까지 파악한 바로는 Element e에는 내용을 최대한 포괄적으로 담는 element를 select 해주는 것이 좋다.

그 밑에서 필요한 내용만 쏙쏙 빼가면 되기 때문

 

가장 큰 news-con을 e에 넣고,

 

그 안에 있는 tit-news 클래스와 lead 클래스를 필요에 맞게 선택하면 되므로

 

for-each문으로 돌릴 때 받는 건 가장 큰 놈으로 한다.

 

##참고

그냥 대충 맞추려고 내가 tit-news를 e에 넣고
lead를 밑에서 부르면 생기는 결과로는

e가 돌아가는 반복 회차마다 페이지에 있는 모든 lead가 출력된다.

 

 

따라서 올바르게 출력한 결과는 다음과 같다.

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

DB에 제대로 넣기

 

 

 

'해결 전'

@Service

public class NewsService {

public void addContToDB(News news) throws  Exception{
        String URL = "https://www.yna.co.kr/economy/all?site=navi_economy_depth02";

        Document doc = Jsoup.connect(URL).get();
        Elements elem = doc.select("div[class=\"news-con\"]");


        int count=1;

        for(Element e:elem.select("div[class=\"news-con\"]")){
            System.out.print(count+" 제목: " + e.select("strong[class=\"tit-news\"]").text());
            System.out.println("   || 내용 : "+e.select("p[class=\"lead\"]").text());

            //e.text()를 DB에 넣기
            news.setContent(e.select("p[class=\"lead\"]").text());
            newsRepository.save(news);
            count++;
            //10개만 출력
            if(count==11){
                break;
            }

        }

    }

 

'해결 후'


@Service
@Transactional

public class NewsService {

public void addContToDB() throws  Exception{
        String URL = "https://www.yna.co.kr/economy/all?site=navi_economy_depth02";

        Document doc = Jsoup.connect(URL).get();
        Elements elem = doc.select("div[class=\"news-con\"]");

        int count=1;

        for(Element e:elem.select("div[class=\"news-con\"]")){
            News news = new News();

            System.out.print(count+" 제목: " + e.select("strong[class=\"tit-news\"]").text());
            System.out.println("   || 내용 : "+e.select("p[class=\"lead\"]").text());

            //e.text()를 DB에 넣기
            news.setContent(e.select("p[class=\"lead\"]").text());
            newsRepository.save(news);
//            news.setId(null);

            count++;

            //10개만 출력
            if(count==11){
                break;
            }

        }

 

차이점



1) 어노테이션 : transactional 이 들어가면서 

원래 작동 방식 = 프로그램이 끝나면 한 번에 push

변경 이후         = 프로그램 진행되는 중에 계속 push



2) 객체 생성 위치 

원래 작동 방식 = 함수 parameter로 받아서 그냥 밑에서 사용함

변경 이후      = for문 안에서 한 회차마다 하나씩 생성함

 

 


이유: 지금까지 나는 한 칸짜리 통에 계속 1번 담기 > 2번이 오면 1번 뺴고 2번 담기 > n번이 오면 n-1번 빼고 n번 담기

이렇게 했으므로 마지막에 통에 저장되어 있는 값은 n번째고 그 값만 새로 추가되었다고 볼 수 있다. (현재까지 이해로는)

따라서 매번 새로운 통을 만들어 그 통에 값을 저장하고, 만들고 저장하고 를 반복하여 데이터를 넣었다고 할 수 있다.

 

 

 

 

 

전공 선배의 해설

오호

 

 

 

 

결과 

 

야호

 

 

 

 


다음 목표 :  저 정보들이 DB에 담겨있고, 그걸 result 창에 띄우기

 

 

그 다음 목표 : AI한테 DB에 있는 내용을 보내서 3문장으로 요약시키고 띄우기 ( 추후에 목표 여러 단계로 나눠라 )