2.5 装备库:框架与工具选型 本节摘要:爬虫工具没有全能冠军,只有场景匹配。本节把装备库分四排货架——轻量脚本、吞吐型框架、浏览器自动化、AI 供料框架(外加商业服务托管),用同一任务在两件装备上的实现对比引出选型逻辑,最后给出可复用的决策函数与部署形态建议。 装备库的四排货架 车间墙边的工具架按"解决问题的重量级"分四排。第一排:轻量脚本,requests 加 BeautifulSoup、httpx 加 lxml 这一族。几十个静态页面、一次性任务、没有渲染没有对抗,写它最快,半天交付。第二排:吞吐型框架,Scrapy 是代表:异步引擎、中间件管线、成熟的调度与去重件,为"百万页级、字段稳定"的任务而生,代价是学习曲线与样板代码。
本节摘要:爬虫工具没有全能冠军,只有场景匹配。本节把装备库分四排货架——轻量脚本、吞吐型框架、浏览器自动化、AI 供料框架(外加商业服务托管),用同一任务在两件装备上的实现对比引出选型逻辑,最后给出可复用的决策函数与部署形态建议。
车间墙边的工具架按"解决问题的重量级"分四排。第一排:轻量脚本,requests 加 BeautifulSoup、httpx 加 lxml 这一族。几十个静态页面、一次性任务、没有渲染没有对抗,写它最快,半天交付。第二排:吞吐型框架,Scrapy 是代表:异步引擎、中间件管线、成熟的调度与去重件,为"百万页级、字段稳定"的任务而生,代价是学习曲线与样板代码。第三排:浏览器自动化,Playwright 与 Selenium:能应付任何渲染与交互,但一切工程件(去重、缓存、频控)都要自己搭,写好了就是自研框架,写不好就是维护噩梦。第四排:AI 供料框架,Crawl4AI 站在这里:底层是 Playwright,上层长出了 Markdown 生成、净化剪枝、声明式抽取、深度爬取、缓存这些 AI 任务需要而裸 Playwright 不提供的器官。货架之外还有"托管区":商业采集服务与云端 API,合规省心、按量计费,但定制空间与数据主权都让渡了出去。

地图上没有"最好"的象限,只有离你任务最近的格子。Crawl4AI 的位置比较微妙——它并非要取代 Scrapy 的吞吐王座,而是把"供料链路"做短:抓完即近用,不希望在裸 HTML 与训练数据之间再手搓三段脚本。
空口对比容易失真,用同一个需求各写一段。任务:抓一个静态列表站的标题与链接,约两百页。Scrapy 版(概念示意,聚焦差异点):
# Scrapy 风格:声明式爬虫 + 管线,工程件由框架供给 import scrapy class ListSpider(scrapy.Spider): name = "list_spider" start_urls = ["https://list.example.com/page/1"] custom_settings = { "DOWNLOAD_DELAY": 2.0, # 频控内置为下载延迟,礼貌参数一等公民 "CONCURRENT_REQUESTS": 8, "ROBOTSTXT_OBEY": True, # 一行配置守住第一层纪律 } def parse(self, response): for item in response.css("div.item"): yield { "title": item.css("h3::text").get(), "link": item.css("a::attr(href)").get(), } next_page = response.css("a.next::attr(href)").get() if next_page: yield scrapy.Request(response.urljoin(next_page), callback=self.parse) # 输出:流水线自动翻页抓完 200 页,日志含 robots 检查与重试记录
Crawl4AI 版做同一件事,重心换成"供料形态":
import asyncio, json from crawl4ai import AsyncWebCrawler, CrawlerRunConfig, CacheMode from crawl4ai import BFSDeepCrawlStrategy from crawl4ai import JsonCssExtractionStrategy schema = { "name": "列表条目", "baseSelector": "div.item", "fields": [ {"name": "title", "selector": "h3", "type": "text"}, {"name": "link", "selector": "a", "type": "attribute", "attribute": "href"}, ], } async def crawl_list(start: str): cfg = CrawlerRunConfig( deep_crawl_strategy=BFSDeepCrawlStrategy(max_depth=200, max_pages=200), extraction_strategy=JsonCssExtractionStrategy(schema=schema), cache_mode=CacheMode.ENABLED, # 二次跑同一任务直接命中缓存 ) async with AsyncWebCrawler() as crawler: results = await crawler.arun(start, config=cfg) rows = [] for r in results: rows.extend(json.loads(r.extracted_content or "[]")) print("总条目:", len(rows)) # 输出:总条目: 3800 return rows asyncio.run(crawl_list("https://list.example.com/page/1"))
两段代码的体感差异就是选型差异:Scrapy 的翻页靠回调链、纪律参数开箱即用;Crawl4AI 的深度爬取一行配置、输出直接是 JSON 行、缓存让重跑零成本。站点是静态的且量级是百万页,Scrapy 的吞吐优势会放大;站点要渲染交互且下游是模型,Crawl4AI 的供料链路优势会放大。
评审会上的选型争论,可以用一个决策函数终结——它把上面的判断固化成可执行的规则:
def choose_tool(pages: str, needs_render: bool, consumer: str, compliance_budget: str) -> str: """四问选型:量级、渲染、下游、合规资源""" if compliance_budget == "无": # 没人管合规就别自建 return "商业采集服务或官方API" if pages == "少量" and not needs_render: return "requests+bs4 轻量脚本" if pages == "海量" and not needs_render: return "Scrapy" if needs_render: return "Crawl4AI" if consumer in {"模型训练", "RAG知识库", "结构化监控"} else "Playwright裸用" return "Crawl4AI(工程件省下的时间大于学习成本)" print(choose_tool("海量", False, "数据仓库", "有")) # 输出:Scrapy print(choose_tool("中等", True, "RAG知识库", "有")) # 输出:Crawl4AI print(choose_tool("少量", False, "一次性分析", "有")) # 输出:requests+bs4 轻量脚本
函数是简化模型,真实决策还有两个变量。团队既有资产:已经有 Scrapy 中间件沉淀的团队,为供料需求加一个 Markdown 管道可能比换框架便宜。部署形态:Crawl4AI 除库形态外还提供容器化的服务端部署,一条命令起本地服务,通过接口提交任务拿结果,适合把采集能力共享给非 Python 的调用方——这个形态在第 5 章的调度中心化里会再遇到。
选型定案,引擎车间的五节到此走完。产出已是"干净但原始"的数据流。下一章进质检流水线:从 AI 需求反推字段、评审数据源、清洗去重、组织仓储、标注增强——数据在这里才真正变成资产的形状。