Chrome Extension으로 웹 페이지의 XPath 정보 가져오기

안녕하세요!

오늘은 Google Chrome Extension을 만들어 웹 페이지의 HTML 요소에 마우스를 올리면 그 요소의 XPath 정보를 얻을 수 있는 신기한 툴을 만들어 볼 거에요.

XPath는 XML 문서의 특정 부분을 찾을 수 있도록 해주는 언어입니다.

웹 스크래핑이나 웹 테스팅에서 자주 사용되죠.


1. Chrome Extension이란?

Chrome Extension은 Google Chrome 브라우저의 기능을 확장시키는 작은 프로그램입니다.

예를 들어, 광고 차단, 비밀번호 관리, 화면 캡쳐 등 다양한 기능을 추가할 수 있어요.



2. 단계별 가이드

2-1. Manifest 파일 생성 (manifest.json)

Chrome Extension을 만들기 위해 가장 먼저 필요한 것은 manifest.json 파일입니다.

이 파일은 확장 프로그램의 메타데이터를 담고 있어요.

{
  "manifest_version": 3,  // Manifest 파일의 버전. Chrome Extension v3 사용하므로 3으로 설정.
  "name": "XPath Finder",  // 확장 프로그램의 이름
  "version": "1.0",        // 확장 프로그램의 버전
  "permissions": ["activeTab"], // 필요한 권한. 현재 활성 탭에 접근하기 위해 "activeTab" 설정.
  "background": {          // 메인  페이지와 팝업 페이지  소통 역할을 해주는 백그라운드 스크립트 설정
    "service_worker": "service-worker.js",
    "type": "module"
  },
  "content_scripts": [     // 메인  페이지에서 동작하는 컨텐트 스크립트 설정
    {
      "matches": ["<all_urls>"], // 모든 URL에 적용
      "js": ["content.js"] // 메인  페이지에서 context.js를 수행 
    }
  ],
  "action": {              // 팝업 UI 설정
    "default_popup": "popup.html"
  }
}


2-2. Content Script (content.js)

content.js는 웹 페이지에 주입되어 실행되는 JavaScript 파일입니다.

이 스크립트를 통해 웹 페이지의 DOM 요소에 접근할 수 있어요.

마우스를 웹 페이지의 요소에 올리면 그 요소가 빨간색 테두리로 강조됩니다.

요소를 클릭하면 XPath 정보가 확장 프로그램으로 전달됩니다.

let isActive = false;
console.log(isActive);

// Xpath 얻어오기
function getXPath(element) {
  let xpath = '';
  for (; element && element.nodeType === 1; element = element.parentNode) {
    let id = Array.from(element.parentNode.children).indexOf(element) + 1;
    id = id > 1 ? `[${id}]` : '';
    xpath = `/${element.tagName}${id}${xpath}`;
  }
  return xpath.length ? `/${xpath}` : '';
}

// mouseover, mouseout 이벤트 시, Element Hightlight 기능 On/Off
document.addEventListener('mouseover', function(e) {
  if (isActive) {
    // Highlight element
    e.target.style.border = "2px solid red";
  }
});

document.addEventListener('mouseout', function(e) {
  if (isActive) {
    // Remove highlight
    e.target.style.border = "";
  }
});

// Click 시, Xpath를 가져와 Background Service에 전달
document.addEventListener('click', function(e) {
  if (isActive) {
    isActive = false;
    e.target.style.border = "";
    e.preventDefault();
    e.stopPropagation();
    
    const xpath = getXPath(e.target);
    // Send XPath to background script or popup
    chrome.runtime.sendMessage({action:'xpathToBackground', xpath: xpath});
  }
}, true);

// Chrome Extension(popup 페이지)에서 activate 요청 시, activate 활성화
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.action === "activate") {
    isActive = !isActive;
  }
});


2-3. Background Script (service-worker.js)

Background Script는 확장 프로그램이 실행되는 동안 지속적으로 실행되는 스크립트입니다.

웹 페이지와 팝업 페이지가 소통할 수 있도록 중간 다리 역할을 합니다.

여기서는 XPath 정보를 받아 처리할 거에요.

let latestXPath = '';

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
  // 메인 웹페이지에서 xpath를 전달해주면, 해당 이벤트를 처리하는 이벤트 핸들러 
  if (message.action = 'xpathToBackground') {
    latestXPath = message.xpath;
    console.log(`Received XPath: ${message.xpath}`);

    // 업데이트된 xpath 정보를 Chrome Extension Popup 페이지에 전달 
    chrome.runtime.sendMessage({action: "updateXPath", xpath: latestXPath});
  }
});


2-4. Popup UI (popup.html)

Popup UI는 사용자가 확장 프로그램 아이콘을 클릭했을 때 나타나는 작은 창입니다.

여기에는 활성화 버튼(Activate)이 있을 거에요.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./popup.css" />
  </head>

  <body>
    <h1>Data Crowling</h1>
    <div><button id="activate">Activate</button></div>
    <div id="result-xpath"></div>
    <script src="./popup.js" type="module"></script>
  </body>
</html>


2-5. Popup UI Javscript (popup.js)

Popup UI에서 동작하는 Javascript 파일입니다.

사용자가 activate 버튼을 누르면, 메인 웹페이지로 activate 요청을 보냅니다.

Background(service-worker.js)로부터 update된 Xpath 정보를 받아 화면에 출력하는 기능도 있습니다.

document.getElementById('activate').addEventListener('click', function() {
    // Send message to content script to activate feature
    
    console.log('activate button clicked');

    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
        chrome.tabs.sendMessage(tabs[0].id, {action: "activate"});
    });
});

// Listen for updates to XPath from the background script
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === "updateXPath") {
    // Update the UI or take other actions
    console.log(`Received updated XPath: ${message.xpath}`);
    document.getElementById('result-xpath').innerHTML = message.xpath;
  }
});



3. 예시: 온라인 쇼핑몰에서 상품 정보 가져오기

예를 들어, 온라인 쇼핑몰에서 특정 상품의 정보를 자동으로 추출하려면 어떻게 할까요?

이 확장 프로그램을 사용하면 상품의 이름, 가격, 이미지 등을 가리키는 XPath를 쉽게 얻을 수 있습니다.

그런 다음, 이 XPath를 사용하여 웹 스크래핑 프로그램을 만들 수 있어요.



4. 마무리

이렇게 간단하게 Chrome Extension을 만들어 웹 페이지의 XPath 정보를 쉽게 얻을 수 있습니다.

이 기능은 웹 개발뿐만 아니라 데이터 분석, 웹 스크래핑 등 다양한 분야에서 유용하게 사용될 수 있어요.

지금까지 Chrome Extension으로 웹 페이지의 XPath 정보를 가져오는 방법에 대해 알아봤습니다.






정규표현식으로 시간 절약하기
당신의 하루에 몇 시간을 더하세요
WPF MVVM 패턴, 그리고 Binding
WPF(Windows Presentation Foundation) 시리즈
AWS SAA 준비 - (4) 비용에 최적화된 아키텍처 설계
(정리) Exam Readiness - AWS Solutions Architect Associate
AWS SAA 준비 - (3) 안전한 아키텍처
(정리) Exam Readiness - AWS Solutions Architect Associate
AWS SAA 준비 - (2) 성능이 뛰어난 아키텍처 설계
(정리) Exam Readiness - AWS Solutions Architect Associate
AWS SAA 준비 - (1) 복원력을 갖춘 아키텍처 설계
(정리) Exam Readiness - AWS Solutions Architect Associate
15분 안에 ToC를 구현해보자!
Vanilla JS로 Table of Contents 구현하기
모듈
모던 자바스크립트 Deep Dive | 48장 | 모듈
에러 처리
모던 자바스크립트 Deep Dive | 47장 | 에러 처리
제너레이터와 async/await
모던 자바스크립트 Deep Dive | 46장 | 제너레이터와 async/await
프로미스
모던 자바스크립트 Deep Dive | 45장 | 프로미스
REST API
모던 자바스크립트 Deep Dive | 44장 | REST API
Ajax
모던 자바스크립트 Deep Dive | 43장 | Ajax
비동기 프로그래밍
모던 자바스크립트 Deep Dive | 42장 | 비동기 프로그래밍
타이머
모던 자바스크립트 Deep Dive | 41장 | 타이머
Set과 Map
모던 자바스크립트 Deep Dive | 37장 | Set과 Map
디스트럭처링
모던 자바스크립트 Deep Dive | 36장 | 디스트럭처링
브라우저의 렌더링 과정
모던 자바스크립트 Deep Dive | 38장 | 브라우저의 렌더링 과정
스프레드 문법
모던 자바스크립트 Deep Dive | 35장 | 스프레드 문법
이터러블
모던 자바스크립트 Deep Dive | 34장 | 이터러블
7번째 데이터 타입 Symbol
모던 자바스크립트 Deep Dive | 33장 | 7번째 데이터 타입 Symbol
String
모던 자바스크립트 Deep Dive | 32장 | String
RegExp
모던 자바스크립트 Deep Dive | 31장 | RegExp
Date
모던 자바스크립트 Deep Dive | 30장 | Date
Math
모던 자바스크립트 Deep Dive | 29장 | Math
DOM
모던 자바스크립트 Deep Dive | 39장 | DOM
Number
모던 자바스크립트 Deep Dive | 28장 | Number
배열
모던 자바스크립트 Deep Dive | 27장 | 배열
이벤트
모던 자바스크립트 Deep Dive | 40장 | 이벤트
ES6 함수의 추가 기능
모던 자바스크립트 Deep Dive | 26장 | ES6 함수의 추가 기능
클래스
모던 자바스크립트 Deep Dive | 25장 | 클래스
this
모던 자바스크립트 Deep Dive | 22장 | this
빌트인 객체
모던 자바스크립트 Deep Dive | 21장 | 빌트인 객체
strict mode
모던 자바스크립트 Deep Dive | 20장 | strict mode
클로저
모던 자바스크립트 Deep Dive | 24장 | 클로저
프로토타입
모던 자바스크립트 Deep Dive | 19장 | 프로토타입
함수와 일급 객체
모던 자바스크립트 Deep Dive | 18장 | 함수와 일급 객체
실행 컨텍스트
모던 자바스크립트 Deep Dive | 23장 | 실행 컨텍스트
생성자 함수에 의한 객체 생성
모던 자바스크립트 Deep Dive | 17장 | 생성자 함수에 의한 객체 생성
프로퍼티 어트리뷰트
모던 자바스크립트 Deep Dive | 16장 | 프로퍼티 어트리뷰트
let, const 키워드와 블록 레벨 스코프
모던 자바스크립트 Deep Dive | 15장 | let, const 키워드와 블록 레벨 스코프
전역 변수의 문제점
모던 자바스크립트 Deep Dive | 14장 | 전역 변수의 문제점
스코프
모던 자바스크립트 Deep Dive | 13장 | 스코프
함수
모던 자바스크립트 Deep Dive | 12장 | 함수
원시 값과 객체의 비교
모던 자바스크립트 Deep Dive | 11장 | 원시 값과 객체의 비교
객체 리터럴
모던 자바스크립트 Deep Dive | 10장 | 객체 리터럴
타입 변환과 단축 평가
모던 자바스크립트 Deep Dive | 9장 | 타입 변환과 단축 평가
제어문
모던 자바스크립트 Deep Dive | 8장 | 제어문
연산자
모던 자바스크립트 Deep Dive | 7장 | 연산자
데이터 타입
모던 자바스크립트 Deep Dive | 6장 | 데이터 타입
표현식과 문
모던 자바스크립트 Deep Dive | 5장 | 표현식과 문
변수
모던 자바스크립트 Deep Dive | 4장 | 변수
Iteration와 Generator
코드스피츠 77 ES6+ 3화 참조
WHATWG 탄생 배경
WHATWG, W3C, HTML의 관련에 대한 역사
프론트엔드(FE) 면접 질문 정리
FE관련 면접 질문 및 답변 정리한 내용입니다.
쿠버네티스(kubernetes, k8s) 용어 정리
쿠버네티스(kubernetes, k8s) 용어 정리
젠킨스(Jenkins) 정리
젠킨스(Jenkins) 정리
Docker 용어 정리
Docker 용어 정리
Git 용어 정리
Git 용어 정리
반응형 웹 디자인(Responsive Web Design)
CSS responsive 에 대하여
JS this에 대하여
this에 대해 알아보자
SQL*PLUS에 대하여
SQL*PLUS 정의 및 사용방법
Oracle에서 SQL Plan 확인하기
Oracle에서 SQL Plan을 확인해보자