본문 바로가기
개발일지/RIDI-Journals 제작기 & 설명서

[리디저널 제작기] 2. 리디 독서노트를 크롤링하는 기능 구현하기

by GiraffePark 2023. 4. 7.
안녕하세요. 박기린 입니다.
본 글은 [ 리디북스의 독서노트 글귀를 복사하는 크롬 확장프로그램 :  RIDI-Journals ]의 제작 과정을 적어놓은 글입니다.

 

 

리디 독서노트 페이지의 글귀들을 팝업창에 복붙하기

// background.js
chrome.runtime.onMessage.addListener(async function (
  request,
  sender,
  sendResponse
) {
  if (request.action === "CHECK") {
    let [activeTab] = await chrome.tabs.query({
      active: true,
      currentWindow: true,
    });
    chrome.scripting.executeScript({
      target: { tabId: activeTab.id },
      files: ["getDom.js"],
    });
  }
});

background.js에 chrome API로부터 'CHECK'라는 메시지를 받을 경우, getDom.js 스크립트 파일이 작동하게 끔 하는 코드 입니다.

 

 

    let [activeTab] = await chrome.tabs.query({
      active: true,
      currentWindow: true,
    });

위의 코드를 통해서 크롬의 현재 탭에 접근할 수 있습니다.

 

 

    chrome.scripting.executeScript({
      target: { tabId: activeTab.id },
      files: ["getDom.js"],
    });

chrome.scripting.executeScript()를 이용해서, content scripts를 실행할 수 있습니다.

인수로 받는 object의 property 중,

  • target은 크롬의 어떤 탭에서 스크립트를 실행할 지 지정하고,
  • files는 실행할 스크립트 파일의 경로를 지정합니다.

 

 

 

 

// getDom.js
function getDom(domTexts) {
  const chunk = [];
  domTexts.forEach(e => {
    chunk.push(e.innerText);
  })

  return chunk;
}

chrome.runtime.sendMessage({
  action: "GET_DOM",
  source: getDom(document.querySelectorAll('.css-135eg6y')),
});

getDom.js입니다.

 

 

 

chrome.runtime.sendMessage({
  action: "GET_DOM",
  source: getDom(document.querySelectorAll('.css-135eg6y')),
});

chrome.runtime.sendMessage()를 이용해서 chrome API로 메시지를 보낼 수 있습니다.

인수로 받는 object의 property 중,

  • action은 Message의 action 유형을 지정하고,
  • source는 Message 안에 함께 전달할 데이터를 지정합니다.

getDom()의 인수로 받는 selector는 

실제 리디북스 독서노트의 글귀에 적용된 class를 전달한 것입니다.

 

 

 

 

// Popup.tsx
import React from "react";

function Popup() {
  const [texts, setTexts] = useState<string[]>([]);
  
  const crawlButtonHandler = (event: React.MouseEvent) => {
    chrome.runtime.sendMessage({ action: "CHECK" });

    chrome.runtime.onMessage.addListener(function (request, sender) {
      console.log(request.source);
      if (request.action == "GET_DOM") {
     	setChunk(request.source);
      }
    });
  };

  return (
    <div className="Popup">
      <button onClick={crawlButtonHandler}>crawl hilights in this page</button>
      {texts.map(text => <p>{text}</p>)}
    </div>
  );
}

export default Popup;

복사한 내용을 팝업창에서 확인할 수 있도록, Popup.tsx를 작성합니다.

 

 

 

  const crawlButtonHandler = (event: React.MouseEvent) => {
    chrome.runtime.sendMessage({ action: "CHECK" });

    chrome.runtime.onMessage.addListener(function (request, sender) {
      console.log(request.source);
      if (request.action == "GET_DOM") {
        console.log(request.source);
        document.body.innerText = request.source;
      }
    });
  };

crawlButtonHandler()는 팝업창의 크롤링 버튼을 누르면 작동하는 핸들러 함수입니다.

실행 과정은

  1. background.js로 'CHECK' 메시지를 전달합니다.
  2. 그러면 background.js는 getDom.js 스크립트를 실행합니다.
  3. getDom은 'GET_DOM' 메시지와 크롤링 데이터를 Popup.tsx로 전달합니다.

 

 

 

크롬 확장프로그램을 빌드한 후, 실제 리디북스 독서노트 페이지에 들어가서 팝업창의 버튼을 누르면,

 

 

 

 

이렇게 내용들이 잘 복사된 것을 확인할 수 있습니다.

 

 

 

 


클립보드에 저장하기 구현

Clipboard API를 사용하면 됩니다. 많은 브라우저에 기본 내장이 되어 있는 API라서 사용성이 훌륭합니다.

// Popup.tsx 중
  
  {...}
  
  const copyButtonHandler = () => {
    navigator.clipboard.writeText(texts.join("\n"));
  };
  
  
  return (
    <div className="Popup">
      <button onClick={crawlButtonHandler}>crawl hilights</button>
      <button onClick={copyButtonHandler}>copy hilights</button>
      {texts.map((text) => (
        <p>{text}</p>
      ))}
    </div>
  );

크롤링한 데이터를 클립보드에 넣어주는 버튼인 Copy 버튼을 만든 후, copyButtonHandler() 함수를 연결합니다.

 

 

굳이 copy 버튼을 따로 만드는 이유가 있습니다.

copy 버튼을 따로 만들지 않고, 크롤링 버튼을 누르면 자동으로 클립보드에 복사까지 되게 하려고 코드를 작성하면 클립보드에는 빈 칸만 저장이 됩니다.

state의 비동기성 때문입니다. state의 비동기성 때문에 crawlButtonHandler 함수에서 texts state를 변경한 후 바로 클립보드에 저장하려고 하면, texts state의 변경사항이 바로 적용되지 않아 클립보드에는 빈 texts만 담깁니다.

그래서 copyButtonHandler()라는 새로운 함수를 이용해서 state가 업데이트 된 후에 클립보드에 저장합니다.

 

 

 

 

  const copyButtonHandler = () => {
    navigator.clipboard.writeText(texts.join("\n"));
  };

navigator.clipboard.writeText()의 인수로 string을 넘기면 아주 간단하게 클립보드에 복사가 됩니다.

 

 

 

vscode에 붙여 넣다 보니 빨간 오류 메시지가 넘쳐납니다..

copy 버튼을 누르고 붙여넣기를 하면, 줄 바꿈까지 잘 인식한 채로 복사가 됩니다.

반응형