Programming/JS +

Node.js 기반 뉴스 크롤링 페이지에 요약 기능 추가하기 (with OpenAI)_실패의 기록

joah.k 2023. 4. 29. 23:59
728x90

Node는 확장성이 좋아서 재미있다 ! 

 

이번엔 ChatGPT 를 개발한 OpenAI 사의 API 를 가지고 뉴스 요약 기능을 추가해보기로 함.

 

Node.js를 이용한 뉴스 기사 크롤링 방법

Node.js 를 이용하여 뉴스 기사를 크롤링해서 웹 페이지에 가져오자! 1. Node.js와 관련된 패키지 설치 서버 구축을 위해 NPM을 통해 패키지를 설치한다. # NPM NPM은 Node.js와 관련한 여러 패키지들을 설

july7k.tistory.com

 

하지만 실패의 기록이므로 혹시나 검색에 걸려 들어오셨다면 참고만...하시길 

 

1.  OpenAI API 사용 준비 - Key 발급


- API 키를 발급 받으려면 먼저 OpenAI에서 회원이어야 하는데, 나는 ChatGPT를 사용하기에 이미 계정이 있었다. 

- 우측 상단의 프로필을 클릭하여 [View API Keys] 메뉴 클릭 

 

- create new secret key 를 클릭하며 개인키를 발급받는다.

- 주의! 공유 및 노출이 안되도록 할 것 

 

 

2.  OpenAI API 적용 및 요약 함수 추가 


적용 방법은 공식 문서를 참고한다.

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

 

그리고 API를 다루기 때문에 따로 환경변수로 빼서 관리하고자 한다.

 

-> 서버 소스 상단에 dotenv 추가 

require('dotenv').config();

-> .env 파일을 생성해 port 번호랑 api 키를 등록 

PORT = 8090
OPENAI_API_KEY= "발급받은 api 키 번호"

-> 서버단에서 환경변수를 가져옴 

const port = process.env.PORT;

const apiKey = process.env.OPENAI_API_KEY;

 

그리고 공식 문서를 참고하여 summary 기능을 추가하기로 하는데.. 

지긋지긋한 429 에러.. 

클라이언트가 일정 시간 동안 요청을 너무 많이 보내서 생긴 에러라 한다. 

 

OpenAI api 에서 무료로 제공하는 쿼터를 초과하여 생긴 문제로 보였다. 

그렇다면 요청을 줄이거나, 더 많은 쿼터를 받아야 하는 건데 나는 무료 한도 안에서 해결하고 싶었다. 

 

최대한 요청을 줄여보고자 했던 노력은 다음과 같다.. 

1. 요청 시간을 조정 - setTimeout() 함수로 요청 시간 조정해보기 -- fail 

const getSummary = async (url) => {
  const { data } = await axios.get(url);
  const text = cheerio.load(data)("body").text();

  return new Promise((resolve, reject) => {
    setTimeout(() => {
      openai.createCompletion({
        model: "text-davinci-002",
        prompt: `Summarize this for a second-grade student:\n\n${text}`,
        max_tokens: 64,
        temperature: 0.7,
        n: 1,
        stop: "\n",
      })
        .then(({ data }) => {
          console.log(data.choices[0].text.trim());
          resolve(data.choices[0].text.trim());
        })
        .catch(reject);
    }, 2000);
  });
};

 

혹시 보내는 뉴스의 양(5개)가 많아서 생긴 문제일까?

2.  '많이 본 뉴스'의 전체 리스트를 가져오지 말고 1개만 가져와 요약 요청을 해보자 -- fail 

// news 크롤링 함수
const getNews = async () => {
  try {
    const { data } = await axios.get(
      "https://news.naver.com/main/main.naver?mode=LSD&mid=shm&sid1=101",
      { responseType: "arraybuffer" }
    );
    const decoded = iconv.decode(Buffer.from(data), "euc-kr");
    const $ = cheerio.load(decoded);
    const ranking_news_arr = $("#_rankingList0 > li > div > div > div").toArray();
    const div = ranking_news_arr[0]; // 첫 번째 뉴스만 가져옴
    const aFirst = $(div).find("a").first(); //div 안에서 처음 나타나는 'a' 태그 선택
    const title = aFirst.text().trim();
    const path = aFirst.attr("href"); //path 변수에 저장하고
    const url = path; //path를 이용, 뉴스기사 전체 url 저장 

    // 언론사
    const aLast = $(div).find("a").last(); // div 내 가장 마지막에 나타나는 'a'태그 선택
    const author = aLast.text().trim(); //문자열 앞뒤 공백 제거
    // 요약
    const summary = await getSummary(url);

    const news = [
      {
        url,
        title,
        author,
        summary,
      },
    ];

    return news;
  } catch (error) {
    console.error(error);
    return []; // 예외가 발생한 경우 빈 배열 반환
  }
};

아마 요청하는 양이 너무 많아서 그런가 싶기도 하고.. 

 

 

결국 OpenAI 사의 API 가 아니라 네이버나 다른 곳에서 제공하는 API 를 사용하는 것이 낫겠다는 생각이 들었다. 

 

 다음에 또 해봐야지.. 

 

 

 

728x90