Scrapling

D4VinciBSD-3-Clause活跃维护

Python 网页抓取框架,从单次请求到大规模爬取都能处理,内置 Playwright 支持,还提供 MCP 服务方便接入 AI 工作流。

🕷️ The BEST Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scrapling_dev

v0.5.1发布于 2026-11-04 20:29 UTC100,848star +1,872 / 7 天10,532fork同步于 2026-11-10 11:18 UTC

怎么上手

由 README 提炼,执行前请确认
pip install scrapling
硬件要求按 README 说明

README 未说明显存或 GPU 要求;StealthyFetcher 等浏览器模式需要本机可运行浏览器环境。

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

一站式 Python 爬虫框架,从单次请求到大规模并发爬取都能覆盖

Python 网页抓取框架,从单次请求到大规模爬取都能处理,内置 Playwright 支持,还提供 MCP 服务方便接入 AI 工作流。

核心能力

  • 用 Fetcher 发 HTTP 请求并模拟 Chrome TLS 指纹
  • 用 StealthyFetcher 渲染 JS 并处理 Cloudflare 验证
  • 用 Spider 并发爬取,支持代理轮换与断点续爬
  • 支持 CSS、XPath、文本与正则多种选择器提取
  • 内置 JSON、JSONL、CSV、XML 导出与 MCP 服务

容易踩的坑

StealthyFetcher 依赖浏览器,首次使用可能需额外安装浏览器或相关依赖;断点续爬需给 Spider 指定 crawldir,且抓取结果要单独保存;README 未说明默认端口等网络配置。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.5.1
  1. v0.5.1Release v0.5.1最新正式版2026-11-04 · 2026-11-04 20:29 UTC

    Small version bump, big browser upgrade! This version lets AI agents follow motion and control drag and drop, adds dedicated remote browser sessions, and brings fixes across parsing, spiders, proxies, and the shell 🚀

    With this update, we extend the limits of current AI models 🔥

    [!NOTE] Follow us on X for daily tips and tricks

    [!WARNING] This release introduces breaking changes to remote browser connections. Connecting to remote browsers now requires a new browser session class. Check the remote-session migration guide before updating.

    🚀 New Stuff and quality of life changes

    • AI agents can now follow motion and take finer control of the mouse (Check the docs):

      • Watch the page in motion: record a short video and share it as a sequence of frames with timestamps to help the agent understand animations, moving controls, and changes that a single screenshot can miss. Pair this with the existing ability to chain actions!
      • Drag, inspect, adjust, and drop: hold a mouse button, move an item or slider, inspect the page while still holding it, then adjust and release. Supports left, right, and middle buttons.
      • Reuse a logged-in remote browser or start with a separate browser context, so the agent can choose the right session for the job.
      • Spend fewer tokens on tool descriptions with shorter text and less repeated guidance.
    • Dedicated remote browser sessions with control over login reuse. RemoteSession and AsyncRemoteSession connect to an existing Chromium browser through an HTTP or WebSocket CDP endpoint. They support the usual stealth session features, including Cloudflare solving. Both classes are also available in the interactive shell. (Check the docs)

      from scrapling.fetchers import RemoteSession
      
      with RemoteSession(cdp_url="http://localhost:9222", new_context=False) as session:
          page = session.fetch("https://example.com")
      
      • new_context=False reuses the browser's existing default context and login state. Its context settings stay in use, and its existing tabs remain open when Scrapling disconnects.
      • The default, new_context=True, creates a separate context and closes it when the session ends. Scrapling uses its own tabs in either mode.
    • Choose your spider's log file encoding with log_file_encoding="utf-8" or another encoding. The default, None, keeps Python's default encoding. (Check the docs)

    🐛 Bug Fixes

    • XPath expressions now return their values correctly, including string(), count(), and boolean(). Empty strings, zero, and false remain available through the usual selector API, by @jayhemnani9910 in #552.

    • Fixed parsing of HTML with no root element, including whitespace-only, comment-only, and doctype-only input, by @rushilnimbalker250 in #536.

    • Fixed find_similar(similarity_threshold=0) when the reference has no attributes to compare, by @Master-Norna in #539.

    • Fixed duplicate robots.txt fetches when concurrent requests reach the same domain, by @RayenMlayeh in #538.

    • Fixed temporary-file collisions during concurrent development-cache writes, by @xixihaha-ha in #546.

    • Malformed links no longer stop extraction of valid links on the same page, by @dajiaohuang in [#548](https://github.com/D4Vinci/Scrapl

  2. v0.5Release v0.52026-10-17 · 2026-10-17 21:43 UTC
    查看更新说明

    Scrapling v0.5 upgrades almost everything: fetching, parsing, spiders, browser automation, AI tools, and docs in ten languages 🚀

    [!NOTE] Follow us on X for daily tips and tricks

    [!WARNING] This release introduces a lot of breaking changes that don't fit here. Check the Migrating to v0.5 guide before updating.

    🚀 New Stuff and quality of life changes

    • A much more capable MCP server for AI agents that can solve almost any CAPTCHA (Check the docs):

      • Complete browser workflows: fill forms, click, hover, scroll, use the keyboard, handle dialogs, and wait for results in one ordered sequence. Supports different field types and slower interactions, with actions stopping at the first error.
      • Read and search the current page without reloading it: extract HTML, Markdown, or text from a whole page or one element. Searchable page snapshots show element roles, names, and positions, with focused views that retain the surrounding context.
      • Run custom JavaScript and take focused screenshots: execute scripts, including async work, with access to the page's own JavaScript. Capture individual elements, the viewport, or the full page as PNG or JPEG.
      • Inspect network activity and reuse logins: examine recorded requests and responses, save and restore browser login state, and interact with elements inside open or closed Shadow DOM. Read recorded traffic before closing the session.
      • Use fewer tokens and get clearer errors: leaner tool descriptions and shared guidance reduce repeated text, while browser and request failures reach agents with useful error messages.
    • See the requests behind the page. Enable record_requests=True to record completed traffic across loads, actions, and tabs, then inspect saved responses without sending requests again. (Check the docs)

      from scrapling.fetchers import StealthySession
      
      with StealthySession(record_requests=True) as session:
          session.fetch("https://example.com", network_idle=True)
          for response in session.network.search(url_pattern=r"/api/", limit=None):
              print(response.url, response.status, response.body)
      
      • Filter by URL, method, resource type, or status; retrieve one response by ID. Inspect headers, sent data, API responses, HTTP errors, and redirects through the usual Response API.
      • Retains supported text bodies with size limits, plus metadata and a reason when a body cannot be saved. The default limit is 1,000 requests. Works with sync and async sessions; saved Python history stays readable after close.
    • Save a login once and reuse it across runs. save_state(path) and load_state(path) save cookies, local storage, and IndexedDB in Playwright-compatible JSON. Both sync and async browser sessions support them. (Check the docs)

      • Load state before fetching or reloading a page. Requires a started, shared browser context without proxy_rotator; tabs, browser settings, and sessionStorage are not saved.
    • Extract open Shadow DOM with pierce_shadow=True, then use CSS or XPath as usual. Available in browser fetchers, sessions, and the CLI's --pierce-shadow option. Preserves slot content without changing the live page. HTML capture excludes closed roots and iframe documents. (Check the docs)

    • Choose how your spider explores a site. CrawlSpider and its subclasses, including ContentSpider, support crawl_strategy="bfs" for oldest-first or "dfs" for newest-first scheduling. Priority still wins, and concurrent page

  3. v0.4.15Release v0.4.152026-08-23 · 2026-08-23 19:43 UTC
    查看更新说明

    One of the biggest releases this year: a reworked MCP server, RAG-ready Markdown in one line, an improved Cloudflare solver, and browser tabs that stay open for automation 🚀

    [!NOTE] Follow us on X for daily tips and tricks

    [!WARNING] This release introduces breaking changes to the MCP server. Check the breaking changes section before updating.

    🚀 New Stuff and quality of life changes

    • Browser tabs now stay open and get reused across requests (Check the docs):
      • All browser sessions keep their tabs after a request, and the next request reuses a free tab instead of opening a new one.
      • Every request re-applies its own settings (timeouts, headers, resource blocking) to the tab it gets, so nothing leaks between requests.
      • Tabs that hit an error are closed and replaced, and the new close_pages() method closes every open tab.
      • The page you fetched stays loaded, so a page_setup function on the next request runs on it before navigating away. That's the building block for chaining automation across requests.
    • Turn any page into clean, LLM-ready Markdown with Response.markdown() (Check the docs):
      from scrapling.fetchers import Fetcher
      
      markdown = Fetcher.get("https://example.com").markdown(main_content_only=True)
      
      • Scripts, styles, and hidden prompt-injection content are always stripped first, the same as the cleaning the MCP server does.
      • Pass css_selector to convert only the elements you need.
      • Available through the new rag extra (pip install "scrapling[rag]"), which the ai/shell/all extras include too.
    • New SiteToMarkdownSpider template to crawl a whole website into a Markdown corpus for RAG pipelines (Check the docs):
      from scrapling.spiders import SiteToMarkdownSpider
      
      class DocsSpider(SiteToMarkdownSpider):
          name = "docs"
          start_urls = ["https://example.com/docs/"]
          allowed_domains = {"example.com"}
          output_dir = "docs_markdown"
      
      result = DocsSpider().start()
      result.items.to_jsonl("docs.jsonl")
      
      • Yields one item per page with url/title/markdown, and the optional output_dir writes one Markdown file per page.
      • max_pages caps the crawl, and since it builds on CrawlSpider, overriding rules() gives you full control over which links get followed.
    • The MCP server is reworked (breaking) (Check the breaking changes and the docs):
      • The 13 tools are now split into two modes: one-shot tools (fetch, bulk_fetch, stealthy_fetch, bulk_stealthy_fetch) that always launch their own browser and show their real defaults, and session tools that work through a session opened once.
      • The new session_fetch tool fetches through a browser session, while open_session now holds the browser-level settings only and returns the session's effective settings for the AI agent.
      • The get tool is renamed to make_request, and it now supports any HTTP method.
      • The new open_request_session and session_make_request tools give the AI persistent HTTP sessions that keep cookies and the browser fingerprint between requests.
      • This also ends fetches resetting the session's settings, first fixed by @Yigtwxx in #418.
    • The MCP server's HTTP transport now requires authentication and binds to localhost by default (breaking) by @yamantaka-sin
  4. v0.4.14Release v0.4.142026-08-10 · 2026-08-10 22:27 UTC
    查看更新说明

    A quick maintenance release to fix installation with uv 🔧

    [!NOTE] Follow us on X for daily tips and tricks

    🐛 Bug Fixes

    • Fixed uv refusing to install v0.4.13 by default and silently falling back to an older version. The previous release required a prerelease version of curl_cffi, which uv doesn't allow unless explicitly enabled. All dependencies now resolve to stable releases. (Fixes #407)

    🙏 Special thanks to the community for all the continuous testing and feedback


    Big shoutout to our Platinum Sponsors

  5. v0.4.13Release v0.4.132026-08-09 · 2026-08-09 19:06 UTC
    查看更新说明

    A new update bringing feed spiders and a smarter MCP server 🎉

    [!NOTE]

    🚀 New Stuff and quality of life changes

    • New feed spider templates. XMLFeedSpider iterates over the nodes of any XML feed (RSS, Atom, product feeds, etc.), and CSVFeedSpider iterates over CSV rows as dictionaries. Both decompress gzipped feeds automatically. (Check the docs)
      from scrapling.spiders import XMLFeedSpider
      
      class RSSSpider(XMLFeedSpider):
          name = "rss"
          start_urls = ["https://example.com/feed.xml"]
      
          async def parse_node(self, response, node):
              yield {"title": node.findtext("title"), "link": node.findtext("link")}
      
      result = RSSSpider().start()
      
    • Upgraded the MCP server to MCP SDK v2 and made it smarter. The server now ships instructions that teach your AI agent how to use the tools efficiently; every tool declares annotations so clients like Claude Code can auto-approve the read-only ones; tool descriptions are leaner to save tokens; and the server advertises its version and logo to MCP clients. (Check the docs)
    • Added a scrapling-mcp command that maps directly to scrapling mcp, so registering Scrapling with MCP clients and registries that expect a single command is now a one-liner.
    • Unpinned Playwright/Patchright and browser versions. The generated browser User-Agent now always matches the exact Chromium version your installed Playwright/Patchright drives, so Scrapling no longer pins their versions and you can upgrade them freely. Run scrapling install --force after updating to refresh the browsers.

    🐛 Bug Fixes

    • Fixed importing Scrapling crashing with a browserforge ValueError when the fingerprints data package lags behind the browser versions. (Fixes #394, #396, and #400)
    • Fixed the MCP bulk browser tools mis-sizing their page pools, which made bulk_fetch fail on batches of more than 50 URLs and bulk_stealthy_fetch fetch all URLs through a single tab, by @Yigtwxx in #393.

    Project

    • New AI Contribution Policy: AI-assisted contributions are welcome but must be disclosed in the PR or issue; submissions that look like undisclosed AI output get labeled and closed.

    🙏 Special thanks to the community for all the continuous testing and feedback


    Big shoutout to our Platinum Sponsors

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Scrapling is a Python Web Scraping framework that brings fast HTTP requests, stealth browsers, powerful parsing, and concurrent crawling into one library.

    Scrape static pages, render JavaScript, interact with websites, and extract data from the API calls behind them. Build crawlers with reusable sessions, proxy rotation, automatic retries, pause/resume, and built-in data exports.

    Use it from Python, the terminal, or your AI agent through its MCP server and Agent Skill. From extracting a few fields to collecting a whole website as clean Markdown, Scrapling covers the full scraping workflow.

    What you can do with Scrapling

    • Fetch & interact: Fast HTTP requests, stealth browsers, JavaScript rendering, Cloudflare Turnstile/Interstitial handling, persistent sessions, and background API capture.
    • Parse & extract: CSS, XPath, text and regex search, adaptive element tracking, similar-element matching, and clean Markdown output.
    • Crawl & export: Concurrent spiders, proxy rotation, retries, AutoThrottle, pause/resume, streaming, ready-made templates, and JSON/JSONL/CSV/XML exports.
    • Scrape with AI or from your terminal: An MCP server for AI agents to browse and extract data, an Agent Skill, CLI commands, and an interactive shell.

    Start with a single page:

    from scrapling.fetchers import Fetcher
    
    page = Fetcher.get('https://quotes.toscrape.com/')
    quotes = page.css('.quote .text::text').getall()
    print(quotes)
    

    Or scale up with a spider:

    from scrapling.spiders import Spider, Response
    
    class QuotesSpider(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(),
                }
    
    result = QuotesSpider().start()
    print(len(result.items))
    result.items.to_json("quotes.json")
    

    This prints 10 and saves the quotes and authors to quotes.json.

    Platinum Sponsors

    Do you want to show your ad here? Click here

    Sponsors

    Do you want to show your ad here? Click here and choose the tier that suits you!


    Key Features

    Spiders - A Full Crawling Framework

    • 🕷️ Scrapy-like Spider API: Define spiders with start_urls, async parse callbacks, and Request/Response objects.
    • ⚡ Concurrent Crawling: Configurable concurrency limits, per-domain throttling, and download delays.
    • 🔄 Multi-Session Support: Unified interface for HTTP requests, and stealthy headless browsers in a single spider - route requests to different sessions by ID.
    • 💾 Pause & Resume: Save pending requests and seen URLs with crawldir. Press Ctrl+C to stop gracefully and restart with the same directory.
    • 📡 Streaming Mode: Stream scraped items as they arrive via async for item in spider.stream() with real-time stats - ideal for UI, pipelines, and long-running crawls.
    • 🛡️ Blocked Request Detection: Automatic detection and retry of blocked requests with customizable logic.
    • 🚦 AutoThrottle: Stop guessing delays. The spider tunes the delay of each domain on its own from how fast the website responds, then doubles it (or waits what Retry-After asks) whenever the website starts blocking or rate-limiting you, and speeds back up once it stops.
    • 🤖 Robots.txt Compliance: Optional robots_txt_obey flag that respects Disallow, Crawl-delay, and Request-rate directives with per-domain caching.
    • 🧪 Development Mode: Cache responses to disk on the first run and replay them on subsequent runs - iterate on your parse() logic without re-hitting the target servers.
    • 🧩 Ready-made Spider Templates: Skip the boilerplate with CrawlSpider for rule-based link following, SitemapSpider for sitemap/robots.txt-driven crawls, XMLFeedSpider/CSVFeedSpider for iterating XML/RSS and CSV feeds, and ShopifySpider to collect products from public Shopify stores, one item per variant.
    • 🔗 Link Extraction: A standalone LinkExtractor primitive with allow/deny patterns, domain filters, CSS/XPath scoping, extension filtering, and canonicalization - use it inside the templates or on its own.
    • 📦 Built-in Export: Export results through hooks and your own pipeline or the built-in JSON/JSONL/CSV/XML exporters with result.items.to_json(), to_jsonl(), to_csv(), and to_xml().

    Advanced Websites Fetching with Session Support

    • HTTP Requests: Fast and stealthy HTTP requests with the Fetcher class. Can impersonate browsers' TLS fingerprint, headers, and use HTTP/3.
    • Dynamic Loading: Fetch dynamic websites with full browser automation through the StealthyFetcher class supporting Playwright's Chromium and Google's Chrome.
    • Anti-bot Bypass: Advanced stealth capabilities with StealthyFetcher and fingerprint spoofing. Can easily bypass all types of Cloudflare's Turnstile/Interstitial with automation.
    • Session Management: Persistent session support with FetcherSession and StealthySession classes for cookie and state management across requests.
    • Proxy Rotation: Built-in ProxyRotator with cyclic or custom rotation strategies across all session types, plus per-request proxy overrides.
    • Domain & Ad Blocking: Block requests to specific domains (and their subdomains) or enable built-in ad blocking (~3,500 known ad/tracker domains) in browser-based fetchers.
    • DNS Leak Prevention: Optional DNS-over-HTTPS support to route DNS queries through Cloudflare's DoH, preventing DNS leaks when using proxies.
    • Remote Browsers: Instead of launching a browser locally, connect to one that's already running through CDP with cdp_url, whether it's on the same machine, another host, or a managed browser provider. You can also point any browser fetcher at your own Chromium build with executable_path.
    • Background API Capture: Enable record_requests=True on a browser session, then search its saved responses with session.network.search(limit=None). Read API data and HTTP errors across page loads without sending requests again. History is bounded and saves text response bodies.
    • Async Support: Complete async support across all fetchers and dedicated async session classes.

    Parsing and Data Extraction

    • 🔄 Smart Element Tracking: Relocate elements after website changes using intelligent similarity algorithms.
    • 🎯 Smart Flexible Selection: CSS selectors, XPath selectors, filter-based search, text search, regex search, and more.
    • 🔍 Find Similar Elements: Automatically locate elements similar to found elements.

    AI Features

    • 🤖 MCP Server: Let AI chatbots and agents (Claude/Cursor/etc) scrape through Scrapling with HTTP requests, browser actions, screenshots, saved login state, and background API responses. Uses our stealthy browser with the right tools to enable suitable AI models to bypass any CAPTCHA is faces while working (not to mention our Cloudflare solver). It uses a lot of methods to reduce the content sent to the model, block ads, and protect it against Prompt-Injection. Remote browsers over CDP and HTTP transport with authentication options are included. (demo video)
    • 🧠 Agent Skill: A ready-to-install Agent Skill that teaches coding agents the whole library, so the code they write with Scrapling matches the current API instead of guessing.
    • 📚 RAG-ready Markdown: Turn any page into clean, sanitized, LLM-ready Markdown with one line (page.markdown()), or crawl a whole website into a Markdown corpus with the ContentSpider template, all without an LLM in the loop. (docs)

    High-Performance & battle-tested Architecture

    • 🚀 Lightning Fast: Optimized performance outperforming most Python scraping libraries.
    • 🔋 Memory Efficient: Optimized data structures and lazy loading for a minimal memory footprint.
    • ⚡ Fast JSON Serialization: 10x faster than the standard library.
    • 🏗️ Battle tested: Not only does Scrapling have 92% test coverage and full type hints coverage, but it has been used daily by hundreds of Web Scrapers over the past year.

    Developer/Web Scraper Friendly Experience

    • 🎯 Interactive Web Scraping Shell: Optional built-in IPython shell with Scrapling integration, shortcuts, and new tools to speed up Web Scraping scripts development, like converting curl requests to Scrapling requests and viewing requests results in your browser.
    • 🚀 Use it directly from the Terminal: Optionally, you can use Scrapling to scrape a URL without writing a single line of code!
    • 🛠️ Rich Navigation API: Advanced DOM traversal with parent, sibling, and child navigation methods.
    • 🧬 Enhanced Text Processing: Built-in regex, cleaning methods, and optimized string operations.
    • 📝 Auto Selector Generation: Generate robust CSS/XPath selectors for any element.
    • 🔌 Familiar API: Similar to Scrapy/BeautifulSoup with the same pseudo-elements used in Scrapy/Parsel.
    • 🤝 Drop-in Scrapy Integration: Already invested in Scrapy? Decorate any callback with scrapling_response to parse the responses you already fetch with Scrapling's parser, no rewrite needed.
    • 📘 Complete Type Coverage: Full type hints for excellent IDE support and code completion. The entire codebase is automatically scanned with PyRight and MyPy with each change.
    • 🔋 Ready Docker image: With each release, a Docker image containing all browsers is automatically built and pushed.

    Getting Started

    Let's give you a quick glimpse of what Scrapling can do without deep diving.

    Basic Usage

    HTTP requests with session support

    from scrapling.fetchers import Fetcher, FetcherSession
    
    with FetcherSession(impersonate='chrome') as session:  # Use latest version of Chrome's TLS fingerprint
        page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
        quotes = page.css('.quote .text::text').getall()
    
    # Or use one-off requests
    page = Fetcher.get('https://quotes.toscrape.com/')
    quotes = page.css('.quote .text::text').getall()
    

    Advanced stealth mode

    from scrapling.fetchers import StealthyFetcher, StealthySession
    
    with StealthySession(headless=True, solve_cloudflare=True) as session:  # Keep the browser open until you finish
        page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
        data = page.css('#padded_content a').getall()
    
    # Or use one-off request style, it opens the browser for this request, then closes it after finishing
    page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare', solve_cloudflare=True)
    data = page.css('#padded_content a').getall()
    

    Full browser automation

    from scrapling.fetchers import StealthyFetcher, StealthySession
    
    with StealthySession(headless=True, disable_resources=False, network_idle=True) as session:  # Keep the browser open until you finish
        page = session.fetch('https://quotes.toscrape.com/', load_dom=False)
        data = page.xpath('//span[@class="text"]/text()').getall()  # XPath selector if you prefer it
    
    # Or use one-off request style, it opens the browser for this request, then closes it after finishing
    page = StealthyFetcher.fetch('https://quotes.toscrape.com/')
    data = page.css('.quote .text::text').getall()
    

    Spiders

    Build full crawlers with concurrent requests, multiple session types, and pause/resume:

    from scrapling.spiders import Spider, Response
    
    class QuotesSpider(Spider):
        name = "quotes"
        start_urls = ["https://quotes.toscrape.com/"]
        concurrent_requests = 10
        
        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(),
                }
                
            next_page = response.css('.next a')
            if next_page:
                yield response.follow(next_page[0].attrib['href'])
    
    result = QuotesSpider().start()
    print(f"Scraped {len(result.items)} quotes")
    result.items.to_json("quotes.json")
    

    Use multiple session types in a single spider:

    from scrapling.spiders import Spider, Request, Response
    from scrapling.fetchers import FetcherSession, AsyncStealthySession
    
    class MultiSessionSpider(Spider):
        name = "multi"
        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():
                # Route protected pages through the stealth session
                if "protected" in link:
                    yield Request(link, sid="stealth")
                else:
                    yield Request(link, sid="fast", callback=self.parse)  # explicit callback
    

    Pause and resume long crawls with checkpoints by running the spider like this:

    QuotesSpider(crawldir="./crawl_data").start()
    

    With crawldir set, press Ctrl+C to save pending requests and seen URLs. Restart with the same crawldir to resume. Save scraped items separately.

    Or skip writing the crawling logic altogether with the ready-made templates, like pulling an entire Shopify store's catalog:

    from scrapling.spiders import ShopifySpider
    
    class MyStore(ShopifySpider):
        target_website = "example.com"
    
    result = MyStore().start()  # Every product in the store, one item per variant
    

    The template reads products exposed through public collection endpoints, one item per variant.

    Advanced Parsing & Navigation

    from scrapling.fetchers import Fetcher
    
    # Rich element selection and navigation
    page = Fetcher.get('https://quotes.toscrape.com/')
    
    # Get quotes with multiple selection methods
    quotes = page.css('.quote')  # CSS selector
    quotes = page.xpath('//div[@class="quote"]')  # XPath
    quotes = page.find_all('div', {'class': 'quote'})  # BeautifulSoup-style
    # Same as
    quotes = page.find_all('div', class_='quote')
    quotes = page.find_all(['div'], class_='quote')
    quotes = page.find_all(class_='quote')  # and so on...
    # Find element by text content
    quotes = page.find_by_text('Albert Einstein', first_match=False)
    
    # Advanced navigation
    quote_text = page.css('.quote')[0].css('.text::text').get()
    quote_texts = page.css('.quote').css('.text::text').getall()  # Chained selectors
    first_quote = page.css('.quote')[0]
    author = first_quote.css('.author::text').get()
    next_quote = first_quote.next
    parent_container = first_quote.parent
    
    # Element relationships and similarity
    similar_elements = first_quote.find_similar()
    below_elements = first_quote.below_elements
    

    You can use the parser right away if you don't want to fetch websites like below:

    from scrapling.parser import Selector
    
    page = Selector("<html>...</html>")
    

    And it works precisely the same way!

    Async Session Management Examples

    import asyncio
    from scrapling.fetchers import FetcherSession, AsyncStealthySession
    
    async def main():
        async with FetcherSession(http3=True) as http_session:  # `FetcherSession` is context-aware and can work in both sync/async patterns
            page1 = await http_session.get('https://quotes.toscrape.com/')
            page2 = await http_session.get('https://quotes.toscrape.com/page/2/', impersonate='chrome')
            print(len(page1.css('.quote')), len(page2.css('.quote')))
    
        async with AsyncStealthySession(max_pages=2) as browser_session:
            urls = ['https://quotes.toscrape.com/js/', 'https://quotes.toscrape.com/js/page/2/']
            pages = await asyncio.gather(*(browser_session.fetch(url, wait_selector='.quote') for url in urls))
            print([len(page.css('.quote')) for page in pages])
    
    asyncio.run(main())
    

    CLI & Interactive Shell

    Scrapling includes a powerful command-line interface:

    asciicast

    Launch the interactive Web Scraping shell

    pip install "scrapling[shell]"
    scrapling shell
    

    Extract pages to a file directly without programming. Use --css-selector to pick the content, or --ai-targeted to select and sanitize the body content. Use .txt for text, .md for Markdown, or .html for HTML.

    scrapling extract get 'https://quotes.toscrape.com/' quotes.md
    scrapling extract get 'https://quotes.toscrape.com/' quotes.txt --css-selector '.quote' --impersonate 'chrome'
    scrapling extract fetch 'https://quotes.toscrape.com/js/' quotes.md --css-selector '.quote' --wait-selector '.quote' --no-headless
    scrapling extract fetch 'https://nopecha.com/demo/cloudflare' captchas.html --css-selector '#padded_content a' --solve-cloudflare
    

    [!NOTE] There are many additional features, but we want to keep this page concise, including the MCP server and the interactive Web Scraping Shell. Check out the full documentation here

    Performance Benchmarks

    Scrapling isn't just powerful-it's also blazing fast. The following benchmarks compare Scrapling's parser with the latest versions of other popular libraries.

    Text Extraction Speed Test (5000 nested elements)

    #LibraryTime (ms)vs Scrapling
    1Scrapling1.991.0x
    2Parsel/Scrapy2.061.035
    3Raw Lxml2.561.286
    4PyQuery23.98~12x
    5Selectolax197.02~99x
    6MechanicalSoup1545.15~776.5x
    7BS4 with Lxml1562.1~785.0x
    8BS4 with html5lib3412.73~1714.9x

    Element Similarity & Text Search Performance

    Scrapling's adaptive element finding capabilities significantly outperform alternatives:

    LibraryTime (ms)vs Scrapling
    Scrapling2.31.0x
    AutoScraper12.585.47x

    All benchmarks represent averages of 100+ runs. See benchmarks.py for methodology.

    Installation

    Scrapling requires Python 3.10 or higher:

    pip install scrapling
    

    [!IMPORTANT] This installation only includes the parser engine and its dependencies, without any fetchers or commandline dependencies. So importing anything from scrapling.fetchers or scrapling.spiders, like in the examples above, will raise ModuleNotFoundError with this installation alone. If you are going to use any of the fetchers or spiders, install the fetchers' dependencies first as shown below.

    Optional Dependencies

    1. If you are going to use any of the extra features below, the fetchers, or their classes, you will need to install fetchers' dependencies and their browser dependencies as follows:

      pip install "scrapling[fetchers]"
      
      scrapling install           # normal install
      scrapling install  --force  # force reinstall
      

      This downloads all browsers, along with their system dependencies and fingerprint manipulation dependencies.

      Or you can install them from the code instead of running a command like this:

      from scrapling.cli import install
      
      install([], standalone_mode=False)          # normal install
      install(["--force"], standalone_mode=False) # force reinstall
      
    2. Extra features:

      • Install the MCP server feature:
        pip install "scrapling[ai]"
        
      • Install dependencies for (building RAG systems):
        pip install "scrapling[rag]"
        
      • Install shell features (Web Scraping shell and the extract command):
        pip install "scrapling[shell]"
        
      • Install everything:
        pip install "scrapling[all]"
        

      Run scrapling install when you need browser fetchers. HTTP requests do not need a browser installation.

    Docker

    You can also install a Docker image with all extras and browsers with the following command from DockerHub:

    docker pull pyd4vinci/scrapling
    

    Or download it from the GitHub registry:

    docker pull ghcr.io/d4vinci/scrapling:latest
    

    This image is automatically built and pushed using GitHub Actions and the repository's main branch.

    Contributing

    We welcome contributions! Please read our contributing guidelines before getting started.

    Disclaimer

    [!CAUTION] This library is provided for educational and research purposes only. By using this library, you agree to comply with local and international data scraping and privacy laws. The authors and contributors are not responsible for any misuse of this software. Always respect the terms of service of websites and robots.txt files.

    🎓 Citations

    If you have used our library for research purposes please quote us with the following reference:

      @misc{scrapling,
        author = {Karim Shoair},
        title = {Scrapling},
        year = {2024},
        url = {https://github.com/D4Vinci/Scrapling},
        note = {A Python Web Scraping framework for everything from a single request to a full-scale crawl!}
      }
    

    License

    This work is licensed under the BSD-3-Clause License.

    Acknowledgments

    This project includes code adapted from:

    • Parsel (BSD License)-Used for translator submodule