"毎日3,000個の商品価格を手作業で確認してください" — この言葉を聞いても無事な人はいません。実際、国内の多くのEC企業がPythonのクローリングでこの作業を自動化しており、その始まりは驚くほど簡単です。この記事では、ウェブスクレイピングの基礎から、実務で直面する実際の問題まで — 実際に動作するコードと共にまとめました。
目次
- ウェブクローリングとは?
- Pythonクローリング基本 — requests + BeautifulSoup
- 動的ページクローリング — SeleniumとPlaywright
- クローリング時によく遭遇する問題
- クローリングと法的問題 — 必ず知っておくべきこと
- 大規模クローリングの現実 — メンテナンス地獄
- 自作 vs 専門サービス — いつ何を選ぶべきか?
ウェブクローリングとは?
ウェブクローリング(Web Crawling) はプログラムがウェブページを自動的に訪れて必要なデータを抽出する技術です。ウェブスクレイピング(Web Scraping) とも呼ばれ、実務ではこれら2つの用語をほぼ同じ意味で使用します。
[ウェブクローリング基本フロー: HTTPリクエスト → HTML受信 → パース → データ抽出 → 保存](images/seo1-crawling-flow.png)
どこに使われるでしょうか?範囲は広いです。
- 価格モニタリング — 競合他社のショッピングモール3,000個の商品価格を毎日自動収集して最安値を追跡
- 市場調査 — ネイバーショッピング、クーポンなどから製品情報、レビュー、評価データを一括収集
- リード生成 — 潜在顧客の連絡先、企業情報を大量収集して営業に活用
- コンテンツモニタリング — ニュース、SNS、コミュニティで特定のキーワードをリアルタイムで追跡
- データ分析 — 不動産価格、求人情報、学術データなどの大規模データセットの構築
Pythonがクローリングに最も多く使用される理由は明確です。BeautifulSoup、Selenium、Playwrightなどのライブラリが豊富であり、構文が直感的でプロトタイプを素早く作成できるためです。
Pythonクローリング基本 — requests + BeautifulSoup
最も基本的な組み合わせです。 requestsでHTMLを取得し、BeautifulSoupで必要なデータを解析します。静的なHTMLページであればこれだけで十分です。
インストール
pip install requests beautifulsoup4
基本例: ニュースタイトルの収集
import requests
from bs4 import BeautifulSoup
# 1. 웹 페이지 HTML 가져오기
# requests.get()으로 HTTP GET 요청을 보냅니다
url = "https://news.ycombinator.com/"
# 2. User-Agent 헤더 설정
# 헤더 없이 요청하면 봇으로 판단해 차단하는 사이트가 많습니다
# 실제 브라우저처럼 보이도록 User-Agent를 설정합니다
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
response = requests.get(url, headers=headers)
# response.raise_for_status() # HTTP 에러 시 예외 발생 (선택)
# 3. BeautifulSoup으로 HTML 파싱
# html.parser는 파이썬 내장 파서 — 별도 설치 불필요
soup = BeautifulSoup(response.text, "html.parser")
# 4. CSS 선택자로 원하는 요소 추출
# .titleline > a → class="titleline" 하위의 <a> 태그 (뉴스 제목 + 링크)
titles = soup.select(".titleline > a")
for i, title in enumerate(titles, 1):
print(f"{i}. {title.text}")
print(f" 링크: {title['href']}")
このコード20行でHacker Newsのすべてのタイトルとリンクを収集できます。Pythonクローリングの入り口が低いと言われる理由はこれです。
複数ページのクローリング(ページネーション)
実務では1ページだけを収集することはまれです。複数のページを巡回するパターンを知っておけば、ほとんどのリスト型サイトに適用できます。
import requests
from bs4 import BeautifulSoup
import time
# 페이지 번호를 URL에 넣는 패턴 — 대부분의 리스트 페이지가 이 구조
base_url = "https://example-blog.com/posts?page={}"
all_posts = []
for page in range(1, 11): # 1~10페이지 순회
response = requests.get(base_url.format(page), headers=headers)
soup = BeautifulSoup(response.text, "html.parser")
# 각 게시글 카드에서 제목, 날짜, URL 추출
posts = soup.select(".post-item")
for post in posts:
all_posts.append({
"title": post.select_one(".post-title").text.strip(),
"date": post.select_one(".post-date").text.strip(),
"url": post.select_one("a")["href"]
})
# 서버 부하 방지를 위한 요청 간격 설정
# 1초도 짧을 수 있음 — 대상 사이트 robots.txt의 Crawl-delay 확인 권장
time.sleep(1)
print(f"총 {len(all_posts)}개 포스트 수집 완료")
ヒント:
time.sleep()を使用してリクエスト間隔を空けることはウェブスクレイピングの基本マナーです。速すぎるリクエストはサーバーに負荷をかけ、IPブロックの直接的な原因となります。通常、1〜3秒の間隔が安全です。
動的ページクローリング — SeleniumとPlaywright
最近、多くのウェブサイトがJavaScriptでコンテンツをレンダリングしています。React、Vue、Next.jsベースのSPA(Single Page Application)では、requestsでHTMLを取得しても空の<div id="root"></div>だけが表示されます — データはJavaScriptが実行された後にロードされるためです。
このような場合、ブラウザ自動化ツールが必要です。実際のブラウザを起動してJavaScriptを実行し、レンダリングされた結果からデータを抽出する方法です。
[静的クローリング vs 動的クローリング比較: requestsはサーバーHTMLのみ受信, Selenium/PlaywrightはJSレンダリング後DOMアクセス](images/seo1-static-vs-dynamic.png)
Seleniumクローリング例
Seleniumはブラウザ自動化の元祖ツールであり、クローリング関連の情報が最も豊富です。
pip install selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 1. 크롬 브라우저를 헤드리스(화면 없이) 모드로 실행
# 서버 환경에서는 화면이 없으므로 헤드리스 모드 필수
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
try:
# 2. 대상 페이지 접속
driver.get("https://example-spa.com/products")
# 3. JavaScript 렌더링이 끝날 때까지 최대 10초 대기
# WebDriverWait는 요소가 나타나면 즉시 다음 단계로 진행
# 10초 안에 안 나타나면 TimeoutException 발생
WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".product-card"))
)
# 4. 렌더링된 DOM에서 데이터 추출
products = driver.find_elements(By.CSS_SELECTOR, ".product-card")
for product in products:
name = product.find_element(By.CSS_SELECTOR, ".product-name").text
price = product.find_element(By.CSS_SELECTOR, ".product-price").text
print(f"{name}: {price}")
finally:
# 5. 브라우저 종료 — 안 닫으면 메모리 누수 발생
driver.quit()
Playwrightクローリング例(2026年推奨)
PlaywrightはMicrosoftが開発した次世代ブラウザ自動化ライブラリです。Seleniumよりも高速で安定しており、自動待機(auto-wait)機能が組み込まれているため、WebDriverWaitのようなボイラープレートコードが不要です。2026年時点では新しいプロジェクトであればPlaywrightを推奨します。
pip install playwright
playwright install chromium # 브라우저 바이너리 자동 다운로드
from playwright.sync_api import sync_playwright
# Playwright는 컨텍스트 매니저로 리소스를 자동 관리
with sync_playwright() as p:
# 1. Chromium 브라우저를 헤드리스 모드로 실행
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# 2. 대상 페이지 접속
page.goto("https://example-spa.com/products")
# 3. Playwright는 자동으로 요소가 나타날 때까지 대기
# 별도의 WebDriverWait 코드가 필요 없음 — 훨씬 깔끔합니다
cards = page.locator(".product-card").all()
for card in cards:
name = card.locator(".product-name").text_content()
price = card.locator(".product-price").text_content()
print(f"{name}: {price}")
# 4. 브라우저 종료
browser.close()
Selenium vs Playwright — どちらを使うか?
[Selenium vs Playwright比較インフォグラフィック](images/seo1-selenium-vs-playwright.png)
| 比較項目 | Selenium | Playwright |
|---|---|---|
| 速度 | 普通 | 一般的にSeleniumよりも速いと評価されている |
| 自動待機 | 手動設定が必要 | 組み込み |
| ブラウザサポート | Chrome、Firefox、Edge、Safari | Chromium、Firefox、WebKit |
| ネットワークインターセプト | 制限的 | ネイティブサポート |
| 学習リソース | 非常に豊富(10年以上の歴史) | 急速に増加中 |
| 推奨シナリオ | レガシープロジェクト、簡単な自動化 | 新規プロジェクト、大規模クローリング |
クローリング時によく遭遇する問題
ここまで読むと「クローリングはそんなに難しくないのかな?」と思うかもしれません。しかし、実務でPythonクローリングを行うと、コード作成よりもはるかに厄介な問題が待っています。初めてクローラーを作成した開発者のほとんどが直面する問題5つをまとめました。
1. IPブロック
同じIPから繰り返しリクエストが送られると、ほとんどのサイトがブロックします。対処方法はプロキシローテーションとリクエスト間隔の調整ですが、問題はコストです。品質の高いレジデンシャルプロキシは企業ごとにGBあたり5〜15ドル、月額基本料金だけで50〜500ドル程度です。プロキシの品質監視、ブロックされたIPの交換などの管理コストを加えると、軽い費用ではありません。
2. CAPTCHAとボット検出
Cloudflare、PerimeterX、Akamai Bot Manager、DataDomeなど、ボット防止ソリューションは年々洗練されています。reCAPTCHA v3はマウスの動き、スクロールパターン、キー入力速度まで分析します。CAPTCHA解決サービス(2Captchaなど)を使用すると、1〜5セント(タイプによって異なる)の単価ですが、1日10万件だと月間60万ウォン以上になります。費用だけでなく、速度と成功率の管理も容易ではありません。
3. 動的レンダリングと無限スクロール
JavaScriptレンダリングが必要なサイトが増えています。ブラウザインスタンスを立ち上げる必要があるため、ページごとにメモリ300〜500MBを消費し、静的クローリングに比べて速度が5〜10倍遅くなります。同時に50個のブラウザを実行するには、最低16GB RAMサーバーが必要であり、クラウド基準で月額15〜30万ウォン程度のインフラコストがかかります。
4. サイト構造の変更
クローリング対象サイトがデザインを変更したり、HTML構造を変更した場合、クローラーは直ちに壊れます。活発なサイトは2〜3か月ごとに構造が変わります。変更の検出 → コード修正 → テスト → デプロイのサイクルを常に維持する必要があり、対象サイトが20個あれば、年間80〜120回のメンテナンスが必要です。
5. データクリーニング
収集したデータがきれいであると期待することは絶対に避けるべきです。サイトごとにエンコーディング(UTF-8、EUC-KR)が異なり、日付形式(2026.01.30 vs 2026-01-30 vs Jan 30, 2026)が異なり、同じ情報をまったく異なる方法で表現します。経験上、データクリーニング作業は収集自体の時間の30〜50%を追加で消費します。
クローリングと法的問題 — 必ず知っておくべきこと
クローリングは技術的には簡単ですが、法的にはグレーゾーンが広がっています。「スクレイピングできる」と「スクレイピングしてもよい」とはまったく異なる問題です。ビジネス目的のクローリングを行う場合、次の3つを必ず確認してください。
robots.txt — クローリングの基本規約
robots.txtはサイト所有者が「このパスは収集しないでください」と明示するファイルです。法的拘束力があるかについては議論がありますが、事実上業界標準となっています。これを無視したクローリングは訴訟時に不利に働く可能性があります。
# 예시: https://example.com/robots.txt
User-agent: *
Disallow: /private/
Disallow: /api/
Crawl-delay: 2 # 요청 간격 2초 이상 유지 요청
確認方法は簡単です。対象URLの後ろに/robots.txtを追加するだけです(例: https://naver.com/robots.txt)。Disallowで指定されたパスは収集対象から除外され、Crawl-delayがあればその間隔を守る必要があります。
個人情報保護法 — 最も注意すべき領域
韓国の個人情報保護法は個人情報収集時に情報主体の同意を原則としています。クローリングで収集したデータに名前、電話番号、メールアドレスなど個人を識別できる情報が含まれている場合、そのデータを保存または利用すること自体が違法になる可能性があります。
実務での注意点:
- 公開されたウェブページであっても、個人情報は同意なしに収集・利用できません
- 特に連絡先、SNSプロフィール、ユーザーレビュー(ニックネームを含む)には注意が必要
- EU対象サービスの場合はGDPRが適用されます — 違反時には全世界売上の最大4%の罰金が科せられます
- 韓国でも個人情報保護委員会の制裁がますます強化されています
現実的なアドバイス: 価格、製品仕様、市場データなど個人情報を含まないデータの収集が最も安全です。個人情報を含むデータが必要な場合は、必ず法的審査を先に受けてください。
著作権法 — データ自体の権利
ウェブページに掲載されたテキスト、画像、動画などはほとんどが著作権で保護されています。クローリングでデータを収集すること自体は




