문서

문서

ActiCrawl을 사용하여 웹 스크래핑 워크플로를 자동화하는 방법을 알아보세요

API 예제

이 가이드는 ActiCrawl API의 일반적인 사용 사례에 대한 실용적인 예제를 제공합니다. 각 예제에는 여러 프로그래밍 언어의 완전한 코드 스니펫이 포함되어 있습니다.

기본 웹 스크래핑

기사 콘텐츠 추출

블로그 게시물이나 뉴스 기사를 스크래핑하고 깔끔하고 읽기 쉬운 콘텐츠를 얻습니다:

python
import requests

api_key = 'YOUR_API_KEY'

response = requests.post(
    'https://www.acticrawl.com/api/v1/scrape',
    headers={'Authorization': f'Bearer {api_key}'},
    json={
        'url': 'https://techcrunch.com/2024/01/15/openai-gpt-5/',
        'output_format': 'markdown',
        'extract_main_content': True
    }
)

article = response.json()
print(article['data']['content'])

스크린샷 생성

모든 웹페이지의 스크린샷 캡처:

javascript
const axios = require('axios');

async function captureScreenshot(url) {
  const response = await axios.post('https://www.acticrawl.com/api/v1/scrape', {
    url: url,
    output_format: 'screenshot',
    wait_for: 3000  // 페이지 로드를 위해 3초 대기
  }, {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  });

  // 스크린샷을 파일로 저장 (사용 가능한 경우)
  if (response.data.data.content) {
    const fs = require('fs');
    const buffer = Buffer.from(response.data.data.content, 'base64');
    fs.writeFileSync('screenshot.png', buffer);
  }
}

captureScreenshot('https://stripe.com');

전자상거래 데이터 추출

제품 정보 스크래핑

전자상거래 사이트에서 구조화된 제품 데이터 추출:

python
import requests
import json

def scrape_product(product_url):
    response = requests.post(
        'https://www.acticrawl.com/api/v1/scrape',
        headers={'Authorization': 'Bearer YOUR_API_KEY'},
        json={
            'url': product_url,
            'output_format': 'json',
            'execute_js': True,
            'wait_for': 5000,  # 동적 콘텐츠 대기
            'include_only_tags': 'h1,.price,.description,.product-image,.reviews'
        }
    )

    return response.json()

# 사용 예시
product = scrape_product('https://amazon.com/dp/B08N5WRWNW')
print(f"제목: {product['data']['metadata']['title']}")
if product['data']['content']:
    print(f"콘텐츠: {product['data']['content']}")

가격 변동 모니터링

시간에 따른 제품 가격 추적:

javascript
const cron = require('node-cron');
const axios = require('axios');
const fs = require('fs');

async function checkPrice(url) {
  const response = await axios.post('https://www.acticrawl.com/api/v1/scrape', {
    url: url,
    output_format: 'json',
    include_only_tags: '.price,.product-title'
  }, {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  });

  const data = response.data.data;
  const content = data.content; // JSON 객체
  const timestamp = new Date().toISOString();

  // CSV에 가격 기록
  if (content && content.content) {
    fs.appendFileSync('prices.csv', `${timestamp},${content.content}\n`);
  }

  return content;
}

// 매시간 가격 확인
cron.schedule('0 * * * *', () => {
  checkPrice('https://example.com/product');
});

뉴스 및 콘텐츠 수집

여러 뉴스 기사 스크래핑

뉴스 웹사이트에서 기사 수집:

python
import requests
from datetime import datetime

def scrape_news_article(article_url):
    # 개별 기사를 마크다운 출력으로 스크래핑
    response = requests.post(
        'https://www.acticrawl.com/api/v1/scrape',
        headers={'Authorization': 'Bearer YOUR_API_KEY'},
        json={
            'url': article_url,
            'output_format': 'markdown',
            'extract_main_content': True
        }
    )

    return response.json()

def scrape_news_links(base_url):
    # 먼저 홈페이지에서 모든 링크 가져오기
    response = requests.post(
        'https://www.acticrawl.com/api/v1/scrape',
        headers={'Authorization': 'Bearer YOUR_API_KEY'},
        json={
            'url': base_url,
            'output_format': 'links'
        }
    )

    links = response.json()['data']['content']
    article_links = [link for link in links if 'article' in link['url'] or 'story' in link['url']]

    return article_links

# 사용 예시
links = scrape_news_links('https://news.ycombinator.com')
for link in links[:5]:  # 처음 5개 기사 처리
    article = scrape_news_article(link['url'])
    print(f"제목: {article['data']['metadata']['title']}")
    print(f"URL: {link['url']}")
    print(f"내용: {article['data']['content'][:200]}...")
    print("-" * 80)

모든 웹사이트를 RSS 피드로 변환

모든 웹사이트를 RSS 피드로 변환:

javascript
const axios = require('axios');
const RSS = require('rss');

async function websiteToRSS(siteUrl) {
  // 블로그 페이지에서 모든 링크 가져오기
  const linksResponse = await axios.post('https://www.acticrawl.com/api/v1/scrape', {
    url: `${siteUrl}/blog`,
    output_format: 'links'
  }, {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  });

  const blogLinks = linksResponse.data.data.content.filter(link => 
    link.url.includes('/blog/') && !link.url.endsWith('/blog/')
  ).slice(0, 20);

  // RSS 피드 생성
  const feed = new RSS({
    title: `${siteUrl} RSS 피드`,
    description: `${siteUrl}의 최신 게시물`,
    feed_url: `${siteUrl}/rss`,
    site_url: siteUrl,
  });

  // 각 블로그 게시물 스크래핑
  for (const link of blogLinks) {
    const articleResponse = await axios.post('https://www.acticrawl.com/api/v1/scrape', {
      url: link.url,
      output_format: 'markdown',
      extract_main_content: true
    }, {
      headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
    });

    const article = articleResponse.data.data;
    feed.item({
      title: article.metadata.title || link.text,
      description: article.content.substring(0, 300) + '...',
      url: link.url,
      date: new Date(article.metadata.scraped_at)
    });
  }

  return feed.xml();
}

연구 및 데이터 수집

학술 논문 수집

연구 논문과 메타데이터 수집:

python
import requests
import pandas as pd

def collect_research_papers(search_url, query):
    # 참고: 이 예제는 검색 결과를 스크래핑하는 방법을 보여줍니다
    # 실제 검색 엔드포인트는 사이트 구조에 따라 달라집니다

    # 먼저 검색 결과 페이지를 스크래핑
    search_query_url = f"{search_url}/search?q={query.replace(' ', '+')}"

    response = requests.post(
        'https://www.acticrawl.com/api/v1/scrape',
        headers={'Authorization': 'Bearer YOUR_API_KEY'},
        json={
            'url': search_query_url,
            'output_format': 'links',
            'execute_js': True,  # 많은 검색 페이지가 JavaScript를 사용
            'wait_for': 3000
        }
    )

    links = response.json()['data']['content']

    # 논문 링크 필터링 (사이트 구조에 따라 조정)
    paper_links = [link for link in links if '/abs/' in link['url'] or '/paper/' in link['url']][:50]

    # 각 논문의 세부 정보 스크래핑
    papers = []
    for link in paper_links:
        paper_response = requests.post(
            'https://www.acticrawl.com/api/v1/scrape',
            headers={'Authorization': 'Bearer YOUR_API_KEY'},
            json={
                'url': link['url'],
                'output_format': 'json',
                'extract_main_content': True
            }
        )

        paper_data = paper_response.json()['data']
        papers.append({
            'title': paper_data['metadata']['title'],
            'url': link['url'],
            'content': paper_data['content']['content'][:500] if paper_data['content'] else '',
            'scraped_at': paper_data['metadata']['scraped_at']
        })

    # 분석을 위해 DataFrame으로 변환
    df = pd.DataFrame(papers)

    # CSV로 저장
    df.to_csv(f'research_{query.replace(" ", "_")}.csv', index=False)

    return df

# 사용 예시
papers = collect_research_papers(
    'https://arxiv.org',
    'machine learning transformers'
)

웹사이트 변경 감지

웹사이트 변경 사항 모니터링:

javascript
const axios = require('axios');
const crypto = require('crypto');
const nodemailer = require('nodemailer');

async function checkForChanges(url, selector) {
  // 현재 콘텐츠 스크래핑
  const response = await axios.post('https://www.acticrawl.com/api/v1/scrape', {
    url: url,
    output_format: 'html_cleaned',
    include_only_tags: selector
  }, {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  });

  const content = response.data.data.content;
  const hash = crypto.createHash('md5').update(content).digest('hex');

  // 저장된 해시와 비교
  const fs = require('fs');
  const hashFile = 'content-hashes.json';
  let hashes = {};

  if (fs.existsSync(hashFile)) {
    hashes = JSON.parse(fs.readFileSync(hashFile));
  }

  if (hashes[url] && hashes[url] !== hash) {
    // 콘텐츠가 변경됨!
    await sendNotification(url, content);
  }

  // 해시 업데이트
  hashes[url] = hash;
  fs.writeFileSync(hashFile, JSON.stringify(hashes));
}

async function sendNotification(url, newContent) {
  // 이메일 알림 전송
  const transporter = nodemailer.createTransport({
    // 이메일 서비스 구성
  });

  await transporter.sendMail({
    to: 'your-email@example.com',
    subject: `웹사이트 변경됨: ${url}`,
    html: `웹사이트가 업데이트되었습니다:<br><br>${newContent}`
  });
}

SEO 및 마케팅

경쟁사 분석

경쟁사 웹사이트 분석:

python
import requests
from collections import Counter
import re

def analyze_competitor(competitor_url):
    # 먼저 홈페이지에서 모든 링크 가져오기
    links_response = requests.post(
        'https://www.acticrawl.com/api/v1/scrape',
        headers={'Authorization': 'Bearer YOUR_API_KEY'},
        json={
            'url': competitor_url,
            'output_format': 'links'
        }
    )

    all_links = links_response.json()['data']['content']

    # 내부 링크만 필터링
    internal_links = [link for link in all_links if competitor_url in link['url']][:100]

    # 페이지 샘플 분석
    keywords = []
    page_structures = {}

    for link in internal_links[:10]:
        page_response = requests.post(
            'https://www.acticrawl.com/api/v1/scrape',
            headers={'Authorization': 'Bearer YOUR_API_KEY'},
            json={
                'url': link['url'],
                'output_format': 'json',
                'extract_main_content': True
            }
        )

        data = page_response.json()['data']

        # 콘텐츠에서 키워드 추출
        if data['content'] and 'content' in data['content']:
            # 간단한 키워드 추출 (프로덕션에서는 NLP 라이브러리 사용)
            words = re.findall(r'\b\w+\b', data['content']['content'].lower())
            # 일반적인 단어와 짧은 단어 필터링
            meaningful_words = [w for w in words if len(w) > 4]
            keywords.extend(meaningful_words)

        # 페이지 구조 추적
        page_type = 'product' if '/product' in link['url'] else \
                   'blog' if '/blog' in link['url'] else \
                   'category' if '/category' in link['url'] else 'other'
        page_structures[page_type] = page_structures.get(page_type, 0) + 1

    # 키워드 분석
    keyword_freq = Counter(keywords)

    return {
        'total_pages': len(internal_links),
        'page_types': page_structures,
        'top_keywords': keyword_freq.most_common(20)
    }

# 사용 예시
analysis = analyze_competitor('https://competitor.com')
print(f"전체 페이지 수: {analysis['total_pages']}")
print(f"페이지 유형: {analysis['page_types']}")
print(f"상위 키워드: {analysis['top_keywords']}")

콘텐츠 아이디어 생성

업계의 트렌드 토픽 찾기:

javascript
async function findTrendingTopics(industrySites) {
  const allArticles = [];

  // 여러 사이트에서 최근 기사 스크래핑
  for (const site of industrySites) {
    // 각 사이트에서 링크 가져오기
    const linksResponse = await axios.post('https://www.acticrawl.com/api/v1/scrape', {
      url: site,
      output_format: 'links'
    }, {
      headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
    });

    // 기사/블로그 링크 필터링
    const articleLinks = linksResponse.data.data.content.filter(link => 
      link.url.includes('/article') || 
      link.url.includes('/blog') || 
      link.url.includes('/post')
    ).slice(0, 10);

    // 각 기사 스크래핑
    for (const link of articleLinks) {
      const articleResponse = await axios.post('https://www.acticrawl.com/api/v1/scrape', {
        url: link.url,
        output_format: 'markdown',
        extract_main_content: true
      }, {
        headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
      });

      allArticles.push({
        url: link.url,
        title: articleResponse.data.data.metadata.title,
        content: articleResponse.data.data.content
      });
    }
  }

  // 주제와 키워드 추출
  const topics = {};

  allArticles.forEach(article => {
    // 제목과 콘텐츠에서 간단한 키워드 추출
    const text = `${article.title} ${article.content}`.toLowerCase();
    const words = text.match(/\b\w{5,}\b/g) || [];

    // 단어 빈도 계산
    words.forEach(word => {
      topics[word] = (topics[word] || 0) + 1;
    });
  });

  // 빈도순 정렬
  const trending = Object.entries(topics)
    .sort((a, b) => b[1] - a[1])
    .slice(0, 10);

  return trending;
}

// 사용 예시
const sites = [
  'https://techcrunch.com',
  'https://theverge.com',
  'https://wired.com'
];

findTrendingTopics(sites).then(trends => {
  console.log('트렌드 토픽:');
  trends.forEach(([topic, count]) => {
    console.log(`- ${topic}: ${count}번 언급됨`);
  });
});

오류 처리 및 모범 사례

강력한 오류 처리

항상 적절한 오류 처리를 구현하세요:

python
import requests
import time
from requests.exceptions import RequestException

def scrape_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.post(
                'https://www.acticrawl.com/api/v1/scrape',
                headers={'Authorization': 'Bearer YOUR_API_KEY'},
                json={'url': url, 'output_format': 'markdown'},
                timeout=30
            )

            if response.status_code == 200:
                return response.json()
            elif response.status_code == 429:
                # 속도 제한 - 대기 후 재시도
                retry_after = int(response.headers.get('X-RateLimit-Reset', 60))
                print(f"속도 제한됨. {retry_after}까지 대기...")
                time.sleep(60)  # 재시도 전 60초 대기
            else:
                print(f"오류 {response.status_code}: {response.text}")

        except RequestException as e:
            print(f"요청 실패: {e}")

        if attempt < max_retries - 1:
            time.sleep(2 ** attempt)  # 지수 백오프

    return None

배치 처리

여러 URL을 효율적으로 처리:

javascript
async function batchScrape(urls, batchSize = 5) {
  const results = [];

  // URL을 배치로 처리
  for (let i = 0; i < urls.length; i += batchSize) {
    const batch = urls.slice(i, i + batchSize);

    const promises = batch.map(url => 
      axios.post('https://www.acticrawl.com/api/v1/scrape', {
        url: url,
        output_format: 'markdown',
        extract_main_content: true
      }, {
        headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
      }).catch(err => ({ error: err.message, url }))
    );

    const batchResults = await Promise.all(promises);
    results.push(...batchResults);

    // 속도 제한 준수
    if (i + batchSize < urls.length) {
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }

  return results;
}

다음 단계

이 예제들은 ActiCrawl API로 가능한 많은 것들 중 일부만을 보여줍니다. 더 고급 사용 사례를 위해:

  1. 완전한 엔드포인트 문서를 위해 API 참조를 탐색하세요
  2. 프로그래밍 언어용 SDK 및 라이브러리를 확인하세요
  3. 지원 및 토론을 위해 개발자 커뮤니티에 참여하세요
  4. 맞춤형 솔루션을 위해 엔터프라이즈 영업 팀에 문의하세요

즐거운 스크래핑 되세요! 🚀