n8n 웹 크롤링 및 Markdown 변환 워크플로우 만들기

요즘 자주 쓰고 있는 n8n 에서 몇가지 웹 크롤링 작업을 해보았는데, 생각보다 쉽지가 않았던 기억이 있습니다. 나중을 위해서라도 기록을 남기려고, 몇자 적어 봅니다. 

웹크롤링을 해야 할떄 유용하게 쓰일 수 있을 것 같습니다.




1단계: n8n 설치 및 준비

  • n8n이 설치되어 있지 않다면 설치를 진행합니다
  • n8n을 실행하고 워크플로우 생성을 시작합니다

2단계: 새 워크플로우 생성

  1. n8n 대시보드에서 "New Workflow" 버튼을 클릭합니다
  2. 워크플로우에 "Web Crawler to Markdown"과 같은 이름을 부여합니다

3단계: HTTP Request 노드 추가

  1. "+" 버튼을 클릭하여 노드 추가
  2. 검색창에 "HTTP Request" 입력하고 선택
  3. 다음과 같이 설정합니다:
    • Method: GET
    • URL: 크롤링할 웹사이트 URL 입력 (예: https://example.com)
    • Authentication: 필요한 경우 설정
  4. "Execute Node"를 클릭하여 테스트합니다

4단계: HTML 파싱을 위한 Cheerio 노드 추가

  1. HTTP Request 노드에 연결하여 Cheerio 노드 추가
  2. Cheerio 노드 설정:
    • Source Data: HTML에서 추출할 요소 선택
    • Selector: 필요한 HTML 요소의 CSS 선택자 입력 (예: article, div.content, h1, p)
    • Return Value: "All matching elements"

5단계: Markdown 변환 노드 추가 (Function 노드 사용)

  1. Cheerio 노드에 연결하여 Function 노드 추가
  2. 다음과 같은 코드를 작성하여 HTML을 Markdown으로 변환합니다:
// 결과를 저장할 배열 초기화
const markdownItems = [];

// 각 항목을 Markdown으로 변환
for (const item of items) {
  // HTML 내용을 Markdown으로 변환
  let content = '';
  
  // 제목 추출 (있는 경우)
  if (item.title) {
    content += `# ${item.title}\n\n`;
  }
  
  // 본문 내용 변환
  if (item.content) {
    content += turndownService.turndown(item.content);
  } else if (item.html) {
    content += turndownService.turndown(item.html);
  } else {
    // HTML이 직접 선택자로 추출된 경우
    content += turndownService.turndown(item);
  }
  
  markdownItems.push({
    markdown: content,
    url: $node["HTTP Request"].json.url,
    timestamp: new Date().toISOString()
  });
}

6단계: Write Binary File 노드 추가

  1. Function 노드에 연결하여 Write Binary File 노드 추가
  2. 다음과 같이 설정합니다:
    • File Name: '{{node["HTTP Request"].parameter["url"].split("/")[2]}}-{{ now}}.md'
    • Property Name: 'data'
    • Binary Property: 'data'
    • 파일 내용 설정:
    {{$json["markdown"]}}
    
    ---
    Source: {{$json["url"]}}
    Created: {{$json["timestamp"]}}
    


7단계: Function 노드에서 Markdown 데이터를 바이너리로 변환

Function 노드 코드를 수정하여 바이너리 데이터로 변환합니다:

const TurndownService = require('turndown');
const turndownService = new TurndownService();

// 결과를 저장할 배열 초기화
const markdownItems = [];

// 각 항목을 Markdown으로 변환
for (const item of items) {
  // HTML 내용을 Markdown으로 변환
  let content = '';
  
  // 제목 추출 (있는 경우)
  if (item.title) {
    content += `# ${item.title}\n\n`;
  }
  
  // 본문 내용 변환
  if (item.content) {
    content += turndownService.turndown(item.content);
  } else if (item.html) {
    content += turndownService.turndown(item.html);
  } else {
    // HTML이 직접 선택자로 추출된 경우
    content += turndownService.turndown(item);
  }
  
  // 메타데이터 추가
  const sourceUrl = $node["HTTP Request"].json.url;
  const timestamp = new Date().toISOString();
  const fullContent = `${content}\n\n---\nSource: ${sourceUrl}\nCreated: ${timestamp}`;
  
  // 바이너리 데이터로 변환
  const buffer = Buffer.from(fullContent);
  const base64 = buffer.toString('base64');

  markdownItems.push({
    json: {
      url: sourceUrl,
      timestamp: timestamp,
    },
    binary: {
      data: {
        data: base64,
        mimeType: 'text/markdown',
        fileName: `${sourceUrl.split('/')[2]}-${Date.now()}.md`,
      }
    }
  });
}

return markdownItems;

8단계: 워크플로우 저장 및 테스트

  1. 우측 상단의 "Save" 버튼 클릭
  2. "Execute Workflow" 버튼을 클릭하여 전체 워크플로우 테스트
  3. 실행 결과를 확인하고 필요한 경우 조정

9단계: 워크플로우 자동화 (선택 사항)

  1. 워크플로우가 제대로 작동하면 트리거 노드를 추가하여 자동화 가능:
    • Schedule 트리거: 정기적인 크롤링
    • Webhook 트리거: API 호출로 크롤링 시작

추가 팁:

  • 여러 페이지를 크롤링하려면 "Split In Batches" 노드와 루프를 사용하세요
  • 이미지도 함께 다운로드하려면 추가 HTTP Request 노드가 필요합니다
  • 크롤링 간격을 조절하여 웹사이트 서버에 부담을 주지 않도록 하세요

이렇게 구성하면 웹사이트 콘텐츠를 크롤링하여 마크다운 파일로 변환하는 n8n 워크플로우가 완성됩니다.


Popular posts from this blog

Switching from ChatGPT Plus to Perplexity Pro: A User’s Perspective

Meta's VideoJam: The Future of AI Video Generation

Nintendo Switch 2 Joy-Con Features Excite Developers

Xbox Multiplatform Strategy: Insights from Shawn Layden

Grok 3 Release Date

ComfyUI Tips for Non-Developers

A Very Simple Agentic AI Implementation