Skip to content

크롤링시 뉴스 카테고리 필터링 기능 추가하기

KWAKMANBO edited this page Feb 11, 2025 · 1 revision

⚠️ 문제점

응답

 {
      title: '권성동 &quot;野 <b>삼성전자급 6개</b> 기업 <b>육성</b>? 채식주의자가 치킨 뜯는 것&quot;',
      originallink: 'https://news.tvchosun.com/site/data/html_dir/2025/02/10/2025021090085.html',
      link: 'https://n.news.naver.com/mnews/article/448/0000507352?sid=100',
      description: '국민의힘 권성동 원내대표는 더불어민주당 집권플랜본부가 <b>삼성전자급</b> 기업 <b>6개</b>를 키워내겠다고 한 데 대해 &quot;입으로는 친기업 외치면서 속으론 반기업 법안을 만들고 있다&quot;며 &quot;자신이 채식주의라고 외치면서 치킨... ',
      pubDate: 'Mon, 10 Feb 2025 11:05:00 +0900'
    },
  • 클로바 AI를 사용해서 뉴스 요약을 진행하던 도중 크롤링한 뉴스에 상관없는 뉴스까지도 크롤링이 되는 것을 알 수 있었다.

  • 위 JSON객체는 기사를 크롤링 한 후 뉴스 요약 AI가 필요로하는 정보에 맞게 가공한것으로 편하게 기사를 크롤링한 내용이라고 생각하면된다.

  • 위 내용은 삼성전자가 언급이 되지만, 삼성전자와는 관련이 직접적으로는 없기 때문에 필요없는 정보이지만 뉴스 요약 시 사용되는 것을 알 수 있었다.

  • 우리 프로젝트의 뉴스 요약 AI서비스는 코스피 시가총액 상위 10개 기업의 최근 뉴스를 요약해주는 서비스로 주식과 관련된 소식들만 정리해야될 필요가 있었다.

뉴스 기사들을 종류에 맞게 필터링 해보자

  • 이전 크롤링 기능을 개발 할때 분석했던 네이버 HTML을 다시 분석해볼필요가 있었다.

네이버 뉴스에서 기사의 카테고리 요소

  • 네이버 뉴스는 위처럼 내가 지금 읽고 있는 기사와 연관된 카테고리를 하이라이트 해주는 것을 알 수 있다. 위 기사는 IT/과학과 연관된 기사이기 때문에 IT/과학이 하이라이트 된것을 알 수 있다.

  • 네이버 뉴스에는 총 12개의 카테고리가 있지만 정치, 경제, 사회, 생활/문화, IT/과학, 세계를 제외한 다른 카테고리들은 다른 기사 사이트로의 리다이렉션 또는 기사모음이기 때문에 신경 쓰지 않아도 될것 같다.

주식 정보와 관련된 카테고리

  • 위에서 정리한 총 6개의 카테고리 정치, 경제, 사회, 생활/문화, IT/과학, 세계 중에서 주식 정보와 관련된 카테고리에는 어떤것이 있을까?

정치

  • 경제 정책이 주식시장에 영향을 줄 수 있지만, 특정 기업 또는 직접적으로 주식 정보를 다루지 않는 카테고리 이므로 제외

경제

  • 가장 연관이 높은 카테고리로, 코스피 지수 변화, 개별 기업 실적, 금리 및 환율등 주식 시장 전반의 흐름을 다루기 때문에 포함 시켜야됨

사회

  • 주식시장과 직접적인 연관은 없으며, 파업, 기업 스캔들과 같은 대형사건에는 영향을 줄 수 있지만, 다른 카테고리에서도 다룰 수 있는 주제이기 때문에 제외 시키기로 결정

생활/문화

  • 특정 소비트렌드를 알 수는 있지만, 주식 시장 전반을 다루지 않기 때문에 제외 시키기로 결정

IT/과학

  • 삼성전자, 네이버 등과 같은 대기업의 IT 실적 발표, 기술 트렌드, 신사업 투자 등이 주가에 영향을 미치는데 이를 주로 다루는 분야이므로 포함 시키기로 결정

뉴스 기사에서 어떻게 연관 분야를 파악할 수 있을까?

  • 이제 어떤 분야를 뉴스 요약에 포함시키고, 포함시키지 않을지 결정했으니 크롤링 할때 어떻게 분야를 파악할 수 있을지 알아보자

  • 위 사진처럼 현재 내가 읽고 있는 기사에 대한 카테고리는 하이라이트 처리 되어 있는 것을 알 수 있는데 이를 이용하면 될거 같다고 생각했다.

  • 위 뉴스 카테고리와 하이라이트가 HTML에서 어떤 요소로 어떻게 표현되는지 알아보자

<li class="Nlist_item _LNB_ITEM is_active" role="presentation">
						<a href="https://news.naver.com/section/105" class="Nitem_link" role="tab" aria-selected="true" data-clk="lnb.it"><span class="Nitem_link_menu">IT/과학</span></a>
					</li>
  • 각 카테고리들은 <li>태그로 리스트 형식으로 노출 되는 것을 알 수 있었다.

  • 일반적으로 <li>태그는 Nlist_item _LNB_ITEM라는 클래스명을 가지지만, 현재 보고있는 기사와 관련된 카테고리는 Nlist_item _LNB_ITEM is_active라는 카테고리를 가지는 것을 알 수 있었다.

  • 위 클래스을를이용해서 크롤링하는 기사와 연관된 카테고리를 추출해보자

카테고리도 필터링하기

@Injectable()
export class NewsCrawlingService {
  constructor(@Inject('winston') private readonly logger: Logger) {
  }
  private readonly category = {
    ECONOMICS: '경제',
    WORLD: '세계',
    IT: 'IT/과학',
  };

  // 얻어온 뉴스 정보들 중 naver news에 기사가 있는 사이트에서 제목, 본문, 생성 날짜등을 크롤링해오기
  async crawling(stock: string, news: NewsItemDto[]) {
    const crawledNews = await Promise.all(
      news.map(async (n) => {
        const url = decodeURI(n.link);
        return await axios(url, {
          method: 'GET',
          headers: {
            'User-Agent':
              'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
            'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
          },
        }).then(async (r) => {
          const htmlString = await r.data;
          const $ = cheerio.load(htmlString);

          const category = $(
            'li.Nlist_item._LNB_ITEM.is_active .Nitem_link_menu',
          ).text();
          const date = $('span._ARTICLE_DATE_TIME').attr('data-date-time');
          const title = $('#title_area').text();
          const content = $('#dic_area').text();


          return {
            category: category,
            date: date,
            title: title,
            content: content,
            url: url,
          };
        });
      }),
    );
    return {
      stockName: stock,
      news: crawledNews.filter((n) => {
        return (
          n.category === this.category.ECONOMICS ||
          n.category === this.category.IT ||
          n.category === this.category.WORLD
        );
      }),
    } as CrawlingDataDto;
  }
}
  • 기존 date,title,content만 크롤링하던 코드에 category도 함께 크롤링할 수 있도록 로직을 변경했다.

  • const category = $( 'li.Nlist_item._LNB_ITEM.is_active .Nitem_link_menu', ).text();을 추가해서 category도 크롤링 해오도록 했다.

  • return에서는 크롤링한 뉴스중 카테고리가 경제, IT/과학, 세계에 속하는 것들만 반환하도록 filter메서드를 사용했다.

  • 위 처럼 기사들이 잘 크롤링 되는 것을 확인할 수 있다.

팀 빌딩

📚팀 빌딩
📝Git 전략

회의록

1주차

🤝1월 7일
🤝1월 8일
🤝1월 9일

2주차

🤝주간 계획(1월 13일)

3주차

🤝주간 계획(1월 20일)

인공지능 리팩토링 1주차

🤝주간 계획(2월 3일)

인공지능 리팩토링 2주차

🤝주간 계획(2월 10일)

개발일지

AI 리팩토링 기획안

AI 리팩토링 개발일지

성능개선

리팩토링

팀회고

학습 정리

Clone this wiki locally