# Python에서 웹페이지를 Markdown으로 변환

> Python에서 웹페이지를 Markdown으로 변환: requests, 동시성 제한을 둔 비동기 httpx, 배치 작업, 제목 기준 RAG 청킹. US$0.07/1K 페이지부터, KYC 없이.

- URL: https://webreaderapi.com/ko/docs/python/
- 마지막 업데이트: 2026-10-22
- 발행자: WebReaderAPI (https://webreaderapi.com)

대부분의 Python 프로젝트를 다루는 네 가지 레시피: requests로 한 페이지 읽기, httpx로 여러 페이지 동시 읽기, 목록을 배치 작업에 넘기기, Markdown을 벡터 스토어용 청크로 나누기.

**빠른 답변 — Python에서 웹페이지를 Markdown으로 변환하려면 어떻게 하나요?**

`Authorization` 헤더에 `requests.get("https://webreaderapi.com/api/v1/read", params={"url": ...})`과 키를 담아 **WebReaderAPI**를 호출하세요. JSON 응답의 `markdown`에 페이지 본문이 담겨 있습니다. 여러 페이지에는 세마포어와 함께 `httpx.AsyncClient`을 사용하거나 배치 작업을 사용하세요. 2026년 10월 기준 US$0.07/1K 페이지부터 페이지 하나에 1크레딧입니다. KYC 없이, 암호화폐로 결제하세요.

## 무엇을 설치해야 하나요?

Python 3.9 이상과 HTTP 클라이언트 하나면 됩니다. 한 번에 한 페이지를 읽는 스크립트에는 `requests`이면 충분하고, `httpx`는 여러 페이지를 병렬로 처리하는 비동기 지원을 추가합니다. 저희 패키지는 필요 없습니다. API는 순수 HTTPS와 JSON이기 때문입니다.

키는 코드 밖에 두세요. 아래 모든 예제처럼 `WEBREADER_API_KEY` 환경 변수에서 읽고, 프로젝트마다 별도 키를 부여하여 다른 키는 건드리지 않고 하나만 폐기할 수 있게 하세요.

*설치*

```bash
pip install requests httpx
export WEBREADER_API_KEY="your-key"
```

## requests로 한 페이지를 어떻게 읽나요?

`url`과 옵션을 검색 쿼리 파라미터로 보내고, HTTP 오류 시 예외를 발생시키고, 필요한 필드를 읽으세요. 예제는 본문을 유지하고, 모델을 위해 20,000자로 제한하며, 호출 비용을 출력합니다.

*requests: 한 페이지 읽기*

```python
import os

import requests

API = "https://webreaderapi.com/api/v1/read"
HEADERS = {"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]}


def read(url, **options):
    resp = requests.get(API, headers=HEADERS, params={"url": url, **options}, timeout=75)
    if resp.status_code != 200:
        error = resp.json()["error"]
        raise RuntimeError(error["code"] + ": " + error["message"])
    return resp.json()


page = read("https://example.com/docs/getting-started", max_chars=20000)
print(page["title"], page["word_count"], "words", page["credits_used"], "credit(s)")
print(page["markdown"][:500])

```

## httpx로 여러 페이지를 한 번에 어떻게 읽나요?

`httpx.AsyncClient` 하나와 동시성 한도 이하로 설정한 `asyncio.Semaphore`을 사용하세요. 모든 계정에는 동시에 읽는 페이지 수에 대한 한도가 있으며, 대시보드에 표시됩니다. 지원팀이 이를 높일 수 있습니다. 한 페이지의 오류가 다른 페이지를 멈추게 해서는 안 되므로, 예제는 예외를 발생시키는 대신 결과 옆에 오류를 모읍니다.

한도를 초과하면 API가 `429 concurrency_limit`으로 응답합니다. 청구는 되지 않지만 페이지는 읽히지 않습니다. 세마포어를 한도 아래로 유지하는 것이 재시도보다 간단합니다.

*httpx: 최대 10페이지 동시 처리*

```python
import asyncio
import os

import httpx

API = "https://webreaderapi.com/api/v1/read"
HEADERS = {"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]}


async def read_one(client, sem, url):
    async with sem:
        resp = await client.get(API, params={"url": url, "max_chars": 50000})
    body = resp.json()
    if resp.status_code == 200:
        return url, body, None
    return url, None, body["error"]["code"]


async def read_many(urls, limit=10):
    sem = asyncio.Semaphore(limit)
    async with httpx.AsyncClient(headers=HEADERS, timeout=75) as client:
        return await asyncio.gather(*(read_one(client, sem, u) for u in urls))


if __name__ == "__main__":
    urls = [f"https://example.com/blog/post-{n}" for n in range(1, 21)]
    for url, page, error in asyncio.run(read_many(urls)):
        print(url, "->", error or page["title"])

```

## 대신 배치 작업은 언제 사용해야 하나요?

최대 100개의 URL 목록이 있고 각 페이지가 준비되는 즉시 필요하지 않을 때 사용하세요. 배치 작업은 저희 쪽에서 실행되므로 스크립트가 연결을 열어둔 채로 있지 않고 재시도 로직도 수행하지 않습니다. `POST https://webreaderapi.com/api/v1/batch`로 시작한 다음, [배치 및 크롤링 페이지](https://webreaderapi.com/ko/docs/crawl/)에 나온 커서 루프로 작업에서 결과를 수집하세요.

사이트 전체라면 대신 크롤링을 시작해 sitemap과 링크를 따라가게 하세요. 같은 페이지에 페이지마다 `.md` 파일 하나를 작성하는 완전한 루프가 있습니다.

*Batch 작업 시작*

```python
import os

import requests

urls = [f"https://example.com/changelog/{year}" for year in range(2020, 2027)]
resp = requests.post(
    "https://webreaderapi.com/api/v1/batch",
    headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
    json={"urls": urls, "options": {"format": "markdown", "main_content": True}},
    timeout=30,
)
resp.raise_for_status()
print("job:", resp.json()["job_id"])

```

## RAG용으로 Markdown을 어떻게 청크로 나누나요?

먼저 제목을 기준으로 나누고, 그다음 크기를 기준으로 나누세요. 제목은 주제가 바뀌는 지점을 표시하므로 제목에서 시작하는 청크는 검색기가 매칭하기 더 쉽습니다. 각 청크의 메타데이터에 페이지 제목과 제목 경로를 유지하세요. 모델이 올바른 섹션을 인용하는 데 도움이 됩니다.

아래 함수는 별도 라이브러리가 필요 없습니다. `#`에서 `###` 제목 기준으로 자른 다음, 긴 섹션은 빈 줄 기준으로 나누어 문자 예산 이내로 유지합니다. 각 청크와 함께 `final_url`를 저장해, 같은 페이지로 이어지는 두 주소가 중복을 만들지 않게 하세요.

*제목 기준으로 Markdown 청크 나누기*

```python
import re


def chunk_markdown(page, max_chars=2000):
    """Split a /read response into chunks with a heading path and the source URL."""
    chunks, path, buf = [], [], []

    def flush():
        text = "\n".join(buf).strip()
        while text:
            part = text[:max_chars]
            cut = part.rfind("\n\n")
            if len(text) > max_chars and cut > max_chars // 2:
                part = part[:cut]
            chunks.append({"text": part.strip(), "section": " > ".join(path), "title": page.get("title"), "source": page["final_url"]})
            text = text[len(part):].strip()
        buf.clear()

    for line in page["markdown"].splitlines():
        m = re.match(r"^(#{1,3}) (.+)", line)
        if m:
            flush()
            level = len(m.group(1))
            path[:] = path[: level - 1] + [m.group(2).strip()]
        buf.append(line)
    flush()
    return chunks

```

## Python 작업 비용은 얼마인가요?

요청이 아니라 페이지를 세세요. 1 크레딧 = 브라우저 없이 페이지 1회 읽기, 페이지가 JavaScript를 렌더링하는 데 브라우저가 필요하면 2 크레딧. 실패한 요청이나 사이트의 robots.txt가 거부한 요청은 과금되지 않습니다. 브라우저 없이 문서 페이지 2,000개를 읽으면 약 2,000 크레딧을 사용하며, 이는 10,000페이지(US$3.75)로 다섯 번 이상 충당됩니다. 선불 크레딧은 만료되지 않습니다. 사용하지 않은 페이지는 사용할 때까지 계정에 남아 있습니다이므로 한 달에 한 번 실행되는 파이프라인은 읽는 만큼만 사용합니다.

## Python: 자주 묻는 질문

### 공식 Python 패키지가 있나요?

아니요. 이 페이지의 코드면 충분합니다. WebReaderAPI는 일반 HTTPS API이고, `requests`이나 `httpx`가 이를 직접 다룹니다.

### robots.txt가 거부하는 페이지는 어떻게 처리하나요?

에러 코드를 확인하세요. `blocked_by_robots`과 `target_refused`는 최종 응답이며 무료입니다. 기록하고 계속 진행하세요. [에러 페이지](https://webreaderapi.com/ko/docs/errors/)에 상태가 바뀔 수 있는 코드만 재시도하는 재시도 헬퍼가 있습니다.

### Jupyter 노트북에서 API를 사용할 수 있나요?

네. `requests` 레시피는 그대로 작동합니다. 노트북에서는 이미 이벤트 루프가 실행 중이므로 `await read_many(urls)`이 `asyncio.run`를 대체합니다.

### 클라이언트 타임아웃은 얼마로 설정해야 하나요?

API 자체보다 조금 더 길게: 기본값은 30초, 최댓값은 60초이므로 클라이언트 측을 75초로 두면 느린 사이트와 응답을 위한 여유가 생깁니다.

---

WebReaderAPI: WebReaderAPI는 AI 에이전트를 위한 웹 리더 API로, 모든 공개 웹페이지를 깔끔한 Markdown으로 변환하며 신분증 업로드 없이 암호화폐로 결제합니다. US$0.07/1K 페이지부터 시작하는 선불 크레딧은 만료되지 않으며, robots.txt를 준수합니다. KYC 없음 — 신분증도, 셀피도, 서류도 없습니다. 암호화폐로 결제하세요.
