FutureInfra 무료로 시작
문서 · 스크래핑

내 액터 만들기

원하는 액터가 목록에 없으면 직접 만듭니다. Apify 방식 코드(Apify SDK·Crawlee)를 그대로 올리면 격리된 컨테이너에서 돌고, 결과는 준비된 액터와 같은 곳에 쌓여 같은 방법으로 내려받습니다. 요금은 쓴 메모리와 시간만큼입니다.

실행 환경

필요한 도구가 미리 깔려 있습니다. 내 패키지는 아래 의존성 파일에 적으면 실행 전에 설치하고, 다음 실행부터는 저장해 둔 것을 씁니다.

runtime구성시작 파일의존성 파일판
node-playwrightNode.js 22 + Crawlee + Apify SDK + Playwright(Chromium)main.jspackage.jsonNode.js 22 · apify@3 · crawlee@3 · playwright@1.48.2
python-playwrightPython 3.12 + Crawlee for Python + Apify SDK + Playwright(Chromium)main.pyrequirements.txtPython 3.12 · apify >=4,<5 · crawlee >=1,<2

가장 짧은 액터

Actor.getInput() 으로 입력을 받고 Actor.pushData() 로 결과를 한 건씩 저장하면 됩니다. 실행 방식이 Apify 의 로컬 실행과 같아서, Apify SDK·Crawlee 로 쓴 코드를 그대로 올리면 됩니다.

// main.js
import { Actor } from "apify";
import { CheerioCrawler, ProxyConfiguration } from "crawlee";

await Actor.init();
const { startUrls = ["https://example.com"], maxPages = 10 } = (await Actor.getInput()) ?? {};

// 인터넷 요청은 FI_PROXY_URL 프록시로 나갑니다(실행마다 자동으로 들어 있음).
const proxyConfiguration = new ProxyConfiguration({ proxyUrls: [process.env.FI_PROXY_URL] });

const crawler = new CheerioCrawler({
  proxyConfiguration,
  maxRequestsPerCrawl: maxPages,
  async requestHandler({ request, $, enqueueLinks }) {
    await Actor.pushData({ url: request.loadedUrl, title: $("title").text().trim(), h1: $("h1").first().text().trim() });
    await enqueueLinks({ strategy: "same-domain" });
  },
});

await crawler.run(startUrls);
await Actor.exit();
# main.py (runtime: python-playwright)
import asyncio, os
from apify import Actor
from crawlee.crawlers import BeautifulSoupCrawler, BeautifulSoupCrawlingContext
from crawlee.proxy_configuration import ProxyConfiguration

async def main() -> None:
    async with Actor:
        inp = await Actor.get_input() or {}
        crawler = BeautifulSoupCrawler(
            proxy_configuration=ProxyConfiguration(proxy_urls=[os.environ["FI_PROXY_URL"]]),
            max_requests_per_crawl=inp.get("maxPages", 10),
        )

        @crawler.router.default_handler
        async def handler(ctx: BeautifulSoupCrawlingContext) -> None:
            await ctx.push_data({"url": ctx.request.url, "title": ctx.soup.title.get_text(strip=True) if ctx.soup.title else None})

        await crawler.run(inp.get("startUrls", ["https://example.com"]))

asyncio.run(main())

만들고 실행하기

콘솔에서는 스크래핑 › 액터 탭 아래 내 액터 › + 새 액터. 예제 코드 버튼으로 위 코드부터 시작할 수 있습니다.

POST /v1/scrape/my-actors
{
  "name": "my-title-crawler",
  "title": "제목 모으기",
  "runtime": "node-playwright",
  "files": [ { "path": "main.js", "content": "import { Actor } from \"apify\"; …" } ],
  "inputSchema": { … 아래 "입력 형식" … },
  "memoryMb": 1024, "timeoutSec": 600, "maxItems": 10000
}

# 실행 — 만들 때 받은 id 앞에 user: 를 붙입니다
POST /v1/scrape/runs
{ "actor": "user:<id>", "input": { "startUrls": ["https://example.com"] } }
  • 고치기 PUT /v1/scrape/my-actors/<id>(고칠 때마다 버전이 1씩 오릅니다) · 목록 GET /v1/scrape/my-actors · 지우기 DELETE
  • 결과·상태·내려받기·여러 개 한꺼번에·웹훅은 준비된 액터와 같습니다
  • AI 도구에서는 scrape.create_actor·scrape.update_actor 로 AI 가 코드를 써서 올립니다

준비된 액터를 복사해서 고치기

비슷한 액터가 이미 있으면 처음부터 쓰지 말고 복사해서 고치세요. 코드·입력 형식·메모리 설정이 통째로 내 액터로 들어옵니다.

콘솔에서는 액터 카드의 복사해서 고치기. API 로는 이렇게 합니다.

POST /v1/scrape/store/naver-blog-search/fork
{ "name": "my-naver-blog-search" }

201 Created
{ "id": "…", "name": "my-naver-blog-search", "title": "…" }

코드는 GET /v1/scrape/store/<이름> 으로 먼저 읽어 볼 수 있습니다. 복사한 액터는 아래 「내 액터 요금」으로 셈합니다.

입력 형식 (input_schema)

Apify 의 input_schema.json 형식 그대로입니다. 콘솔은 이것으로 입력 칸을 그리고, 실행할 때 빠진 칸은 기본값으로 채웁니다.

{
  "title": "입력",
  "type": "object",
  "schemaVersion": 1,
  "properties": {
    "startUrls": {
      "title": "시작 주소",
      "type": "array",
      "editor": "stringList",
      "prefill": [
        "https://example.com"
      ]
    },
    "maxPages": {
      "title": "최대 페이지 수",
      "type": "integer",
      "default": 10
    }
  },
  "required": [
    "startUrls"
  ]
}
  • type — string·integer·number·boolean·array·object. 모양이 다르면 실행 전에 input_invalid 로 알려 줍니다
  • required 에 적은 칸이 비면 input_required — 칸 이름이 같이 옵니다
  • default 는 비었을 때 넣을 값, prefill 은 콘솔 입력 칸에 미리 채울 값입니다

프록시 자동 연결

실행마다 그 실행만 쓰는 프록시 주소가 환경변수로 들어갑니다. 따로 계정을 만들 필요가 없습니다.

  • FI_PROXY_URL — Crawlee 의 ProxyConfiguration 에 그대로 넣습니다(위 예제 참고)
  • HTTP_PROXY·HTTPS_PROXY 에도 같은 값이 들어 있어, 이 값을 읽는 도구(requests·axios 등)는 설정 없이 프록시로 나갑니다
  • 패키지 설치(package.json·requirements.txt)도 같은 길로 받아 옵니다

내 액터 요금

메모리 × 실제로 돈 시간으로 셉니다. 메모리 1GB로 1시간 돌면 400원(부가세 포함).

  • 예) 메모리 1,024MB 로 10분 돌면 67원
  • 시작할 때 "메모리 × 제한 시간" 최대치만큼 잔액이 있는지 보고, 끝나면 실제로 쓴 만큼만 빠집니다
  • maxCostKrw 를 주면 그 금액 안에서 끝나도록 제한 시간을 맞춥니다
설정고를 수 있는 범위기본값
memoryMb 메모리256~4,096MB1,024MB
timeoutSec 제한 시간60~3,600초600초
maxItems 최대 결과 수1~100,000건10,000건
코드 파일50개, 합쳐서 1MB 까지—
내 액터 수조직당 30개—

결과와 파일

  • Actor.pushData() 로 넣은 것 → 결과(데이터셋). GET /v1/scrape/runs/<id>/items?format=csv 로 내려받습니다
  • Actor.setValue("이름", 내용) 으로 넣은 것 → 파일(스크린샷·PDF 등). GET /v1/scrape/runs/<id>/records 에서 봅니다. 파일 하나 10MB, 실행당 100개, 합쳐서 200MB 까지
  • 로그(log.info·print)는 GET /v1/scrape/runs/<id>/log 와 콘솔 실행 기록에서 봅니다