Scrapling とは?

Scrapling は、開発者 D4Vinci によって作成された適応型の Python ウェブクローラーフレームワークです。2026 年の GitHub Trending で急速に人気を集め、57,000 以上のスターを獲得し、新世代のクローリングツールの代表格となりました。

なぜ Scrapling が必要なのか?

従来のクローラーフレームワーク(Scrapy や BeautifulSoup など)には、主に 3 つの課題がありました。

  1. サイト構造の変化でコードが動作しなくなる: CSS セレクターや XPath は、ページがリニューアルするとすべて崩壊します
  2. アンチボットシステムによるブロック: Cloudflare Turnstile や Akamai などの保護により、通常のリクエストはすぐに 403 エラーになります
  3. 拡張性の低さ: 小規模な取得から大規模な並行クロールへ移行する際、大量のコードを書き直す必要があります

Scrapling の核となる設計思想は "One library, zero compromises"(一つのライブラリ、妥協なし)です。

  • 適応型パーサー: サイト構造を自動学習し、ページ更新後も要素を自動で再特定します
  • 内蔵アンチボット: 追加設定なしで、Cloudflare Turnstile などの主要な保護を回避します
  • Scrapy ライクな API: Scrapy に慣れた開発者はシームレスに移行できます
  • 単一リクエストから全量クロールまで: 同じ API で単純な取得と大規模な並行クローラーの両方をサポートします

Scrapling vs 従来型クローラーツール

機能 BeautifulSoup Scrapy Scrapling
学習コスト 低 中 中
適応型解析 ❌ ❌ ✅
Cloudflare 回避 ❌ プラグイン必要 ✅ 内蔵
並行クロール ❌ ✅ ✅
動的ページ対応 ❌ ミドルウェア必要 ✅ Playwright 内蔵
一時停止/再開 ❌ 拡張機能必要 ✅ 内蔵
ストリーム出力 ❌ ❌ ✅

Scrapling のインストール

環境要件

  • Python 3.8 以上
  • pip パッケージマネージャー

クイックインストール

BASH
pip install scrapling

インストール確認

PYTHON
from scrapling.fetchers import Fetcher

# 基本機能をテスト
p = Fetcher.fetch('https://example.com')
print(p.title)  # ページタイトルを出力

オプションの依存関係

動的なページレンダリング(JavaScript サイト)が必要な場合は、Playwright をインストールしてください。

BASH
pip install playwright
playwright install chromium

クイックスタート:最初のクローラー

例 1: 単純なページ取得

簡単な例から始めましょう。Hacker News のヘッドラインニュースを取得します。

PYTHON
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 を渡すだけで、ターゲット要素を自動で見つけ出せます。

PYTHON
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}")

サイト構造が変更された場合:

PYTHON
# 後続の取得: 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 はこれらの保護を自動で処理できます。

PYTHON
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 を使用します。

PYTHON
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 を使用して高並行の取得を実現します。

PYTHON
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

PYTHON
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()

並行設定

PYTHON
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 で優雅に終了した後、次回起動時に自動で再開されます。

PYTHON
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()

実践ケーススタディ

PYTHON
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 サイト価格監視

PYTHON
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: ストリーム出力(リアルタイム処理)

長時間実行されるクローラーの場合、ストリームモードを使用してデータをリアルタイムで処理できます。

PYTHON
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. プロキシローテーション

PYTHON
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. カスタムエクスポートパイプライン

PYTHON
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. 開発モード(レスポンスキャッシュ)

解析ロジックをデバッグする際、サーバーへの重複リクエストを避けます。

PYTHON
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 を使用してログインをシミュレートします。

PYTHON
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 でダウンロード遅延と並行制限を設定します。

PYTHON
class PoliteSpider(Spider):
    custom_settings = {
        "concurrency": 2,           # 並行数を減らす
        "download_delay": 2,        # 各リクエストの間隔を 2 秒にする
        "robots_txt_obey": True,    # robots.txt を遵守
    }

Q4: Scrapling はどのセレクターをサポートしていますか?

A: CSS セレクターと XPath の両方をサポートしています。

PYTHON
# 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 コミュニティ

この記事が役に立ったと思ったら、ぜひ他の開発者にもシェアしてください!