Hermes Agent Wiki 非公式・日本語wiki
この skill をそのまま使う: GitHub で原文を見る

英語原文・frontmatter 込みで、Hermes が読み込む実体そのままです(このページの本文は日本語版)。

Scrapling

目次

目立たないブラウザ操作と Cloudflare 回避でサイトを収集します。

skill の情報

提供元 追加の skill です。hermes skills install official/research/scrapling で入れられます
パス optional-skills/research/scrapling
バージョン 1.0.0
作者 FEUAZUR
ライセンス MIT
対応プラットフォーム linux, macos, windows
タグ Web Scraping, Browser, Cloudflare, Stealth, Crawling, Spider
関連 skill duckduckgo-search, domain-intel

参考: SKILL.md 全文

Scrapling

Scrapling は、ボット判定の回避、目立たないブラウザ操作、複数ページの巡回をまとめて扱えるウェブ収集の枠組みです。取得のやり方を 3 通り(HTTP、JavaScript を動かすもの、Cloudflare 向けに目立たないもの)そろえ、CLI も一式そなえています。

この skill は学習と調査のためのものです。 使う人は、地域や国際的なデータ収集の法律を守り、サイトの利用規約を尊重してください。

こんなときに使います

  • 変化のない HTML のページを取得するとき(ブラウザを使うツールより速く済みます)
  • JavaScript で描かれるページを、本物のブラウザで取得したいとき
  • Cloudflare Turnstile やボット判定を通り抜けたいとき
  • 複数のページをたどって巡回したいとき
  • 最初から使える web_extract では、ほしいデータが返ってこないとき

導入

pip install "scrapling[all]"
scrapling install

最小構成(HTTP のみ。ブラウザなし):

pip install scrapling

ブラウザ操作だけを足す場合:

pip install "scrapling[fetchers]"
scrapling install

早見表

やり方 クラス 向いている場面
HTTP Fetcher / FetcherSession 変化のないページ、API、たくさんの取得を速く
動的 DynamicFetcher / DynamicSession JavaScript で描かれる内容、SPA
目立たない取得 StealthyFetcher / StealthySession Cloudflare、ボット判定のあるサイト
巡回 Spider リンクをたどる複数ページの巡回

CLI の使い方

変化のないページを取り出す

scrapling extract get 'https://example.com' output.md

CSS セレクタとブラウザのなりすましを付ける場合:

scrapling extract get 'https://example.com' output.md \
  --css-selector '.content' \
  --impersonate 'chrome'

JavaScript で描かれるページを取り出す

scrapling extract fetch 'https://example.com' output.md \
  --css-selector '.dynamic-content' \
  --disable-resources \
  --network-idle

Cloudflare のあるページを取り出す

scrapling extract stealthy-fetch 'https://protected-site.com' output.html \
  --solve-cloudflare \
  --block-webrtc \
  --hide-canvas

POST リクエスト

scrapling extract post 'https://example.com/api' output.json \
  --json '{"query": "search term"}'

出力の形式

出力の形式はファイルの拡張子で決まります:

  • .html -- そのままの HTML
  • .md -- Markdown に変換
  • .txt -- ただのテキスト
  • .json / .jsonl -- JSON

Python: HTTP での取得

一度きりのリクエスト

from scrapling.fetchers import Fetcher

page = Fetcher.get('https://quotes.toscrape.com/')
quotes = page.css('.quote .text::text').getall()
for q in quotes:
    print(q)

セッション(Cookie を保つ)

from scrapling.fetchers import FetcherSession

with FetcherSession(impersonate='chrome') as session:
    page = session.get('https://example.com/', stealthy_headers=True)
    links = page.css('a::attr(href)').getall()
    for link in links[:5]:
        sub = session.get(link)
        print(sub.css('h1::text').get())

POST / PUT / DELETE

page = Fetcher.post('https://api.example.com/data', json={"key": "value"})
page = Fetcher.put('https://api.example.com/item/1', data={"name": "updated"})
page = Fetcher.delete('https://api.example.com/item/1')

プロキシを使う

page = Fetcher.get('https://example.com', proxy='http://user:pass@proxy:8080')

Python: 動的なページ(JavaScript で描かれるもの)

JavaScript の実行が必要なページ(SPA、あとから読み込む内容)にはこちらを使います:

from scrapling.fetchers import DynamicFetcher

page = DynamicFetcher.fetch('https://example.com', headless=True)
data = page.css('.js-loaded-content::text').getall()

特定の要素が出るまで待つ

page = DynamicFetcher.fetch(
    'https://example.com',
    wait_selector=('.results', 'visible'),
    network_idle=True,
)

読み込むものを減らして速くする

フォント、画像、動画・音声、スタイルシートを止めます(25% ほど速くなります):

from scrapling.fetchers import DynamicSession

with DynamicSession(headless=True, disable_resources=True, network_idle=True) as session:
    page = session.fetch('https://example.com')
    items = page.css('.item::text').getall()

ページ操作を自分で書く

from playwright.sync_api import Page
from scrapling.fetchers import DynamicFetcher

def scroll_and_click(page: Page):
    page.mouse.wheel(0, 3000)
    page.wait_for_timeout(1000)
    page.click('button.load-more')
    page.wait_for_selector('.extra-results')

page = DynamicFetcher.fetch('https://example.com', page_action=scroll_and_click)
results = page.css('.extra-results .item::text').getall()

Python: 目立たない取得(ボット判定の回避)

Cloudflare のあるサイトや、指紋を細かく見ているサイトにはこちらを使います:

from scrapling.fetchers import StealthyFetcher

page = StealthyFetcher.fetch(
    'https://protected-site.com',
    headless=True,
    solve_cloudflare=True,
    block_webrtc=True,
    hide_canvas=True,
)
content = page.css('.protected-content::text').getall()

目立たないセッション

from scrapling.fetchers import StealthySession

with StealthySession(headless=True, solve_cloudflare=True) as session:
    page1 = session.fetch('https://protected-site.com/page1')
    page2 = session.fetch('https://protected-site.com/page2')

要素の選び方

どの取得方法でも Selector のオブジェクトが返り、次のメソッドが使えます:

CSS セレクタ

page.css('h1::text').get()              # First h1 text
page.css('a::attr(href)').getall()      # All link hrefs
page.css('.quote .text::text').getall() # Nested selection

XPath

page.xpath('//div[@class="content"]/text()').getall()
page.xpath('//a/@href').getall()

探すためのメソッド

page.find_all('div', class_='quote')       # By tag + attribute
page.find_by_text('Read more', tag='a')    # By text content
page.find_by_regex(r'\$\d+\.\d{2}')       # By regex pattern

似た形の要素

同じような組み立ての要素をまとめて見つけます(商品の一覧などで役に立ちます):

first_product = page.css('.product')[0]
all_similar = first_product.find_similar()
el = page.css('.target')[0]
el.parent                # Parent element
el.children              # Child elements
el.next_sibling          # Next sibling
el.prev_sibling          # Previous sibling

Python: 巡回の仕組み

リンクをたどって複数のページを巡回するときに使います:

from scrapling.spiders import Spider, Request, Response

class QuotesSpider(Spider):
    name = "quotes"
    start_urls = ["https://quotes.toscrape.com/"]
    concurrent_requests = 10
    download_delay = 1

    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 response.follow(next_page)

result = QuotesSpider().start()
print(f"Scraped {len(result.items)} quotes")
result.items.to_json("quotes.json")

取得方法を使い分ける巡回

リクエストごとに取得のやり方を振り分けます:

from scrapling.fetchers import FetcherSession, AsyncStealthySession

class SmartSpider(Spider):
    name = "smart"
    start_urls = ["https://example.com/"]

    def configure_sessions(self, manager):
        manager.add("fast", FetcherSession(impersonate="chrome"))
        manager.add("stealth", AsyncStealthySession(headless=True), lazy=True)

    async def parse(self, response: Response):
        for link in response.css('a::attr(href)').getall():
            if "protected" in link:
                yield Request(link, sid="stealth")
            else:
                yield Request(link, sid="fast", callback=self.parse)

巡回を止めて再開する

spider = QuotesSpider(crawldir="./crawl_checkpoint")
spider.start()  # Ctrl+C to pause, re-run to resume from checkpoint

つまずきやすいところ

  • ブラウザの導入が必要: pip で入れたあと scrapling install を実行してください。これをしないと DynamicFetcherStealthyFetcher は失敗します
  • 待ち時間の単位: DynamicFetcher / StealthyFetcher の待ち時間は ミリ秒 です(既定は 30000)。Fetcher の待ち時間は です
  • Cloudflare の回避: solve_cloudflare=True を付けると取得に 5〜15 秒ほど増えます。必要なときだけ有効にしてください
  • 資源の使い方: StealthyFetcher は本物のブラウザを動かします。同時に走らせる数は抑えてください
  • 法律: 収集の前に、必ず robots.txt とサイトの利用規約を確認してください。このライブラリは学習と調査のためのものです
  • Python の版: Python 3.10 以上が必要です