Scrapling とは?
Scrapling は、開発者 D4Vinci によって作成された適応型の Python ウェブクローラーフレームワークです。2026 年の GitHub Trending で急速に人気を集め、57,000 以上のスターを獲得し、新世代のクローリングツールの代表格となりました。
なぜ Scrapling が必要なのか?
従来のクローラーフレームワーク(Scrapy や BeautifulSoup など)には、主に 3 つの課題がありました。
- サイト構造の変化でコードが動作しなくなる: CSS セレクターや XPath は、ページがリニューアルするとすべて崩壊します
- アンチボットシステムによるブロック: Cloudflare Turnstile や Akamai などの保護により、通常のリクエストはすぐに 403 エラーになります
- 拡張性の低さ: 小規模な取得から大規模な並行クロールへ移行する際、大量のコードを書き直す必要があります
Scrapling の核となる設計思想は "One library, zero compromises"(一つのライブラリ、妥協なし)です。
- 適応型パーサー: サイト構造を自動学習し、ページ更新後も要素を自動で再特定します
- 内蔵アンチボット: 追加設定なしで、Cloudflare Turnstile などの主要な保護を回避します
- Scrapy ライクな API: Scrapy に慣れた開発者はシームレスに移行できます
- 単一リクエストから全量クロールまで: 同じ API で単純な取得と大規模な並行クローラーの両方をサポートします
Scrapling vs 従来型クローラーツール
| 機能 | BeautifulSoup | Scrapy | Scrapling |
|---|---|---|---|
| 学習コスト | 低 | 中 | 中 |
| 適応型解析 | ❌ | ❌ | ✅ |
| Cloudflare 回避 | ❌ | プラグイン必要 | ✅ 内蔵 |
| 並行クロール | ❌ | ✅ | ✅ |
| 動的ページ対応 | ❌ | ミドルウェア必要 | ✅ Playwright 内蔵 |
| 一時停止/再開 | ❌ | 拡張機能必要 | ✅ 内蔵 |
| ストリーム出力 | ❌ | ❌ | ✅ |
Scrapling のインストール
環境要件
- Python 3.8 以上
- pip パッケージマネージャー
クイックインストール
pip install scrapling
インストール確認
from scrapling.fetchers import Fetcher
# 基本機能をテスト
p = Fetcher.fetch('https://example.com')
print(p.title) # ページタイトルを出力
オプションの依存関係
動的なページレンダリング(JavaScript サイト)が必要な場合は、Playwright をインストールしてください。
pip install playwright
playwright install chromium
クイックスタート:最初のクローラー
例 1: 単純なページ取得
簡単な例から始めましょう。Hacker News のヘッドラインニュースを取得します。
from scrapling.fetchers import Fetcher
# HTTP リクエストを送信
page = Fetcher.fetch('https://news.ycombinator.com/')
# CSS セレクターを使ってデータを抽出
stories = page.css('.titleline > a')
for story in stories[:5]: # 最初の 5 件だけ取得
title = story.text
link = story.attrs.get('href', '')
print(f"タイトル: {title}")
print(f"リンク: {link}")
print("-" * 40)
出力例:
タイトル: Show HN: I built a real-time code collaboration tool
リンク: https://github.com/example/collab-tool
----------------------------------------
タイトル: Ask HN: What's your favorite Python library in 2026?
リンク: https://news.ycombinator.com/item?id=123456
----------------------------------------
例 2: 適応型解析(Auto-save)
Scrapling の核心機能は適応型解析です。初めてデータを取得する際に auto_save=True を有効にすると、Scrapling はページ構造を学習して特徴を保存します。サイトがリニューアルした後は、adaptive=True を渡すだけで、ターゲット要素を自動で見つけ出せます。
from scrapling.fetchers import Fetcher
page = Fetcher.fetch('https://quotes.toscrape.com/')
# 初回取得: auto_save を有効化
quotes = page.css('.quote', auto_save=True)
for quote in quotes[:3]:
text = quote.css('.text::text').get()
author = quote.css('.author::text').get()
print(f"{text} — {author}")
サイト構造が変更された場合:
# 後続の取得: adaptive=True を渡す
page = Fetcher.fetch('https://quotes.toscrape.com/')
quotes = page.css('.quote', adaptive=True) # 新しい構造に自動適応!
for quote in quotes[:3]:
text = quote.css('.text::text').get()
author = quote.css('.author::text').get()
print(f"{text} — {author}")
💡 仕組み: Scrapling は要素の多种類の特徴(タグタイプ、近隣のテキスト、属性パターンなど)を記録します。CSS クラス名が変わっても、他の特徴を通じて要素を再特定できます。
高度な機能
1. Cloudflare Turnstile の回避
多くのサイトでは Cloudflare Turnstile やその他のアンチボットシステムを使用しています。Scrapling の StealthyFetcher はこれらの保護を自動で処理できます。
from scrapling.fetchers import StealthyFetcher
# 適応モードを有効化
StealthyFetcher.adaptive = True
# Cloudflare を自動回避
page = StealthyFetcher.fetch(
'https://example-protected-site.com',
headless=True, # ヘッドレスブラウザモード
network_idle=True # ネットワークがアイドルになるまで待機
)
# 通常通りデータを抽出
products = page.css('.product-item')
for product in products:
name = product.css('.name::text').get()
price = product.css('.price::text').get()
print(f"{name}: {price}")
主要パラメーターの説明:
- headless=True: ヘッドレスブラウザを使用し、実際のユーザー行動をシミュレートします
- network_idle=True: すべてのネットワーク通信が完了するのを待ってから抽出します(SPA アプリケーションに適しています)
- adaptive=True: 適応型解析を有効化します
2. 動的ページレンダリング(Playwright)
JavaScript レンダリングが必要なサイトには、DynamicFetcher を使用します。
from scrapling.fetchers import DynamicFetcher
page = DynamicFetcher.fetch(
'https://spa-example.com',
wait_for='.content-loaded', # 特定の要素が表示されるまで待機
timeout=30000 # タイムアウト時間(ミリ秒)
)
# 動的に読み込まれたコンテンツを抽出
articles = page.css('article')
for article in articles:
title = article.css('h2::text').get()
summary = article.css('.summary::text').get()
print(f"{title}\n{summary}\n")
3. 非同期並行取得
AsyncFetcher を使用して高並行の取得を実現します。
import asyncio
from scrapling.fetchers import AsyncFetcher
async def fetch_multiple_pages():
urls = [
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3',
'https://example.com/page/4',
'https://example.com/page/5',
]
# 並行してリクエストを送信
pages = await AsyncFetcher.fetch_many(urls, concurrency=3)
for url, page in zip(urls, pages):
if page:
title = page.title
print(f"{url}: {title}")
else:
print(f"{url}: リクエスト失敗")
asyncio.run(fetch_multiple_pages())
Spider フレームワーク:大規模クロール
Scrapling は Scrapy に似た Spider フレームワークを提供しており、大規模な並行クロールをサポートします。
基本 Spider
from scrapling.spiders import Spider, Response
class QuoteSpider(Spider):
name = "quotes"
start_urls = ["https://quotes.toscrape.com/"]
async def parse(self, response: Response):
# 現在のページから名言を抽出
for quote in response.css('.quote'):
yield {
"text": quote.css('.text::text').get(),
"author": quote.css('.author::text').get(),
"tags": quote.css('.tag::text').getall()
}
# 次のページへ
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield self.follow(next_page, callback=self.parse)
# クローラーを起動
QuoteSpider().start()
並行設定
class MultiPageSpider(Spider):
name = "multi-page"
start_urls = [f"https://example.com/page/{i}" for i in range(1, 101)]
# 並行数を設定
custom_settings = {
"concurrency": 5, # 最大並行数
"download_delay": 1, # ダウンロード遅延(秒)
"robots_txt_obey": True, # robots.txt を遵守
}
async def parse(self, response: Response):
title = response.css('h1::text').get()
yield {"url": response.url, "title": title}
MultiPageSpider().start()
一時停止と再開
Scrapling はチェックポイントベースの永続化をサポートしています。Ctrl+C で優雅に終了した後、次回起動時に自動で再開されます。
class LongRunningSpider(Spider):
name = "long-crawl"
start_urls = ["https://large-site.com/"]
custom_settings = {
"checkpoint_dir": "./checkpoints", # チェックポイントディレクトリ
}
async def parse(self, response: Response):
# データを抽出...
yield {"data": "..."}
# クロールを継続
for link in response.css('a::attr(href)').getall():
yield self.follow(link, callback=self.parse)
LongRunningSpider().start()
実践ケーススタディ
ケース 1: GitHub Trending プロジェクトの取得
from scrapling.fetchers import Fetcher
def scrape_github_trending():
page = Fetcher.fetch('https://github.com/trending')
repos = page.css('.Box-row')
trending = []
for repo in repos[:10]:
name = repo.css('h2 a::text').get('').strip()
description = repo.css('p.col-9::text').get('').strip()
stars = repo.css('[href$=stargazers] span::text').get('').strip()
language = repo.css('[itemprop=programmingLanguage]::text').get('').strip()
trending.append({
"name": name,
"description": description,
"stars": stars,
"language": language
})
return trending
if __name__ == "__main__":
results = scrape_github_trending()
for repo in results:
print(f"📦 {repo['name']}")
print(f" {repo['description'][:80]}...")
print(f" ⭐ {repo['stars']} | 📝 {repo['language']}")
print()
ケース 2: EC サイト価格監視
from scrapling.fetchers import StealthyFetcher
import json
from datetime import datetime
def monitor_prices():
urls = [
"https://amazon.com/dp/B08N5WRWNW",
"https://amazon.com/dp/B0BSHF7WHW",
"https://amazon.com/dp/B09G9FPHY6",
]
results = []
for url in urls:
page = StealthyFetcher.fetch(url, headless=True)
title = page.css('#productTitle::text').get('').strip()
price = page.css('.a-price .a-offscreen::text').get('').strip()
results.append({
"url": url,
"title": title,
"price": price,
"timestamp": datetime.now().isoformat()
})
print(f"✅ {title[:50]}... - {price}")
# JSON に保存
with open('price_monitor.json', 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"\n📊 {len(results)} 件の価格データを price_monitor.json に保存しました")
if __name__ == "__main__":
monitor_prices()
ケース 3: ストリーム出力(リアルタイム処理)
長時間実行されるクローラーの場合、ストリームモードを使用してデータをリアルタイムで処理できます。
from scrapling.spiders import Spider, Response
class StreamingSpider(Spider):
name = "streaming-demo"
start_urls = ["https://quotes.toscrape.com/"]
async def parse(self, response: Response):
for quote in response.css('.quote'):
item = {
"text": quote.css('.text::text').get(),
"author": quote.css('.author::text').get()
}
yield item # すべて完了を待たずに即時产出
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield self.follow(next_page, callback=self.parse)
# ストリーム消費
async def main():
spider = StreamingSpider()
async for item in spider.stream():
# 各アイテムをリアルタイムで処理
print(f"受信: {item['text'][:50]}... by {item['author']}")
# データベースへの保存やメッセージキューへの送信などが可能
import asyncio
asyncio.run(main())
高度なテクニック
1. プロキシローテーション
from scrapling.spiders import Spider, Response
class ProxySpider(Spider):
name = "proxy-spider"
start_urls = ["https://httpbin.org/ip"]
custom_settings = {
"proxy_list": [
"http://proxy1.example.com:8080",
"http://proxy2.example.com:8080",
"http://proxy3.example.com:8080",
],
"proxy_rotation": "per_request", # リクエストごとにプロキシをローテーション
}
async def parse(self, response: Response):
ip = response.json().get('origin')
print(f"現在の IP: {ip}")
2. カスタムエクスポートパイプライン
from scrapling.spiders import Spider, Response
import csv
class CSVSpider(Spider):
name = "csv-export"
start_urls = ["https://quotes.toscrape.com/"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.csv_file = open('quotes.csv', 'w', newline='', encoding='utf-8')
self.writer = csv.writer(self.csv_file)
self.writer.writerow(['Text', 'Author', 'Tags'])
async def parse(self, response: Response):
for quote in response.css('.quote'):
text = quote.css('.text::text').get()
author = quote.css('.author::text').get()
tags = ', '.join(quote.css('.tag::text').getall())
self.writer.writerow([text, author, tags])
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield self.follow(next_page, callback=self.parse)
def close(self, reason):
self.csv_file.close()
print(f"✅ データが quotes.csv に保存されました")
3. 開発モード(レスポンスキャッシュ)
解析ロジックをデバッグする際、サーバーへの重複リクエストを避けます。
from scrapling.spiders import Spider, Response
class DevSpider(Spider):
name = "dev-mode"
start_urls = ["https://example.com"]
custom_settings = {
"dev_mode": True, # 開発モードを有効化
"cache_dir": "./http_cache", # キャッシュディレクトリ
}
async def parse(self, response: Response):
# 初回実行: レスポンスをディスクにキャッシュ
# 以降の実行: ネットワークリクエストなしでディスクから直接読み取り
title = response.css('h1::text').get()
yield {"title": title}
よくある質問
Q1: Scrapling と Scrapy の違いは何ですか?
A: Scrapling は Scrapy の現代的な強化版と見なせます。 - 適応型解析: Scrapy のセレクターはページリニューアル後に機能しなくなりますが、Scrapling は自動で適応します - 内蔵アンチボット: Scrapy では Cloudflare を回避するために追加のミドルウェアが必要ですが、Scrapling は开箱即用です - よりシンプルな API: Scrapling の Fetcher API は、小規模な高速取得により適しています
Scrapy に慣れている場合、Scrapling への移行にはほとんど学習コストがかかりません。
Q2: ログイン後のページをどう処理すればよいですか?
A: StealthyFetcher または DynamicFetcher を使用してログインをシミュレートします。
from scrapling.fetchers import DynamicFetcher
page = DynamicFetcher.fetch(
'https://example.com/login',
headless=True,
wait_for='#dashboard' # ログイン後の遷移を待機
)
# ログイン操作を実行(Playwright 経由)
page.page.fill('#username', 'your_username')
page.page.fill('#password', 'your_password')
page.page.click('#login-button')
page.page.wait_for_selector('#dashboard')
# これでログイン後のコンテンツを取得できます
data = page.css('.private-data::text').getall()
Q3: ブロックを避けるためにクロール速度を制限するには?
A: Spider でダウンロード遅延と並行制限を設定します。
class PoliteSpider(Spider):
custom_settings = {
"concurrency": 2, # 並行数を減らす
"download_delay": 2, # 各リクエストの間隔を 2 秒にする
"robots_txt_obey": True, # robots.txt を遵守
}
Q4: Scrapling はどのセレクターをサポートしていますか?
A: CSS セレクターと XPath の両方をサポートしています。
# CSS セレクター
page.css('.class-name::text').get()
page.css('#id-name').getall()
# XPath
page.xpath('//div[@class="example"]/text()').get()
まとめ
Scrapling は 2026 年で最も注目すべき Python クローラーフレームワークです。適応型解析、アンチボット能力、Scrapy ライクな API を完璧に組み合わせ、開発者が最小限のコードで最も安定したクローラーを実現できるようにします。
核心の優位性のおさらい: - ✅ 適応型パーサー: ページリニューアル後も要素を自動で再特定 - ✅ 内蔵アンチボット: 追加設定なしで Cloudflare Turnstile を回避 - ✅ 単一リクエストから全量クロールまで: 同じ API ですべてのシナリオをカバー - ✅ 並行、一時停止/再開、ストリーム出力: 本番環境レベルの機能を完備
リソースリンク: - GitHub リポジトリ - 公式ドキュメント - Discord コミュニティ
この記事が役に立ったと思ったら、ぜひ他の開発者にもシェアしてください!