第 1 课

装好 Scrapling,用 extract 和 Fetcher 抓取解析网页

在虚拟环境里装 scrapling[all]==0.5,用 extract get 把网页存成 Markdown、用 -s 选元素、用 --ai-targeted 去掉隐藏内容,用 Fetcher 加 CSS/XPath 取名言和翻页链接,用 find_by_text、find_similar、generate_css_selector 少写选择器,再用 auto_save 加 adaptive 在模拟改版后找回元素。

图文20 分钟Scrapling 官方文档 ↗

课程目录第 1 / 3 课

学习位置仅保存在当前浏览器,有效期 180 天。

01 / 图文教材

图文教材

本课对照的官方页面:安装、HTTP 请求、选择元素、自适应抓取、extract 命令。命令与输出在 Linux x86_64 云主机上实测(Scrapling 0.5,Python 3.13),输出为节选。

这一课装好 Scrapling,先用命令行不写代码把网页存成 Markdown,再用 Python 的 Fetcher 抓页面、用 CSS 和 XPath 取数据,最后试一下它最有特色的「自适应」定位:网页改版后,旧选择器失效了也能把元素找回来。全程不需要账号,也不花钱。

第 1 步:建虚拟环境并安装

Scrapling 要求 Python 3.10 或更高版本。官方把功能拆成几个可选依赖:只装 scrapling 只有解析器;[fetchers] 加上抓取器;[shell] 加上命令行 extract;[ai] 加上 MCP 服务器(第 3 课用);[all] 全部装上。本课锁定 0.5 并一次装全:

mkdir scrapling-lab && cd scrapling-lab
python3 -m venv .venv
source .venv/bin/activate
pip install "scrapling[all]==0.5"
scrapling --version

对照结果:

Scrapling, version 0.5

第 2 课要用浏览器抓取器,还需要下载浏览器和系统依赖。HTTP 抓取(本课)不需要这一步,可以先跳过:

scrapling install

这条命令会下载 Chromium 和指纹相关依赖,并调用 Playwright 安装系统库。测试机下载浏览器成功,但系统库那一步因为软件源临时报错退出(exit 1);测试机本来已有 Chrome 需要的系统库,所以第 2 课的浏览器抓取照样能跑。如果你也遇到这种情况,换个时间或换个软件源重跑一次即可。

第 2 步:不写代码,用 extract 把网页存成 Markdown

先用官方练习站 quotes.toscrape.com 试一下。extract get 发一个普通 HTTP 请求,按输出文件的后缀决定格式:.md 存 Markdown,.html 存 HTML,.txt 存纯文本。

scrapling extract get "https://quotes.toscrape.com/" quotes.md
head -12 quotes.md

对照结果(节选,长行已折行,路径已省略):

INFO: Fetched (200) <GET https://quotes.toscrape.com/>
      (referer: https://www.google.com/)
INFO: Content successfully saved to '.../quotes.md'
Quotes to Scrape

[Quotes to Scrape](/)
=====================

[Login](/login)

“The world as we have created it is a process of our
thinking. ...” by Albert Einstein [(about)](/author/Albert-Einstein)

日志里的 referer: https://www.google.com/ 是 Scrapling 默认加的,让请求看起来像从搜索结果点进来的。

加 -s(--css-selector)只保存匹配的元素;加 --ai-targeted 只留正文,并去掉隐藏元素、零宽字符和 HTML 注释,防止网页里藏着写给 AI 的指令(提示词注入)。要喂给大模型的内容建议都加上:

scrapling extract get "https://quotes.toscrape.com/" ai.md \
  -s ".quote" --ai-targeted
head -9 ai.md

对照结果:

“The world as we have created it is a process of our thinking.
It cannot be changed without changing our thinking.”
by Albert Einstein
[(about)](/author/Albert-Einstein)

Tags:
[change](/tag/change/page/1/)
[deep-thoughts](/tag/deep-thoughts/page/1/)
[thinking](/tag/thinking/page/1/)

第一行名言为排版折行。一个小坑:输出成 .txt 时,多个匹配元素的文字会直接连在一起,没有换行。实测 -s ".quote .author" 存成 authors.txt,得到的是 Albert EinsteinJ.K. RowlingAlbert Einstein...。需要逐条分开时,存成 .md,或者改用下一步的 Python 写法。

第 3 步:用 Fetcher 抓页面,用 CSS 和 XPath 取数据

新建 first.py:

from scrapling.fetchers import Fetcher

page = Fetcher.get('https://quotes.toscrape.com/')
print(page.status, page.url)
quotes = page.css('.quote .text::text').getall()
print(len(quotes), quotes[0][:40])
first = page.css('.quote')[0]
print(first.css('.author::text').get())
print(first.xpath('.//a[contains(@href, "tag")]/text()').getall())
link = page.css('li.next a::attr(href)').get()
print('next:', link, '->', page.urljoin(link))
python first.py

对照结果(已去掉 INFO 日志行):

200 https://quotes.toscrape.com/
10 “The world as we have created it is a pr
Albert Einstein
['change', 'deep-thoughts', 'thinking', 'world']
next: /page/2/ -> https://quotes.toscrape.com/page/2/

几个要点:

  • Fetcher.get() 返回的页面对象可以直接选元素,不用再交给 BeautifulSoup 或 lxml。
  • ::text 取文字、::attr(href) 取属性,写法和 Scrapy/Parsel 一样;.get() 取第一个,.getall() 取全部。
  • css() 和 xpath() 可以混用,也可以在某个元素上继续选。
  • page.urljoin() 把相对链接 /page/2/ 拼成完整地址,下一课爬虫翻页会用到。
  • Fetcher 底层用 curl_cffi,默认模仿真实浏览器的 TLS 指纹和请求头,比 requests 更不容易被识别成脚本。

第 4 步:不写选择器,按文字找元素、找相似元素

不确定选择器怎么写时,可以先按文字找到一个元素,再让 Scrapling 找出页面上结构相同的其他元素。新建 similar.py:

from scrapling.fetchers import Fetcher

page = Fetcher.get('https://quotes.toscrape.com/')
einstein = page.find_by_text('Albert Einstein', first_match=True)
print(einstein.tag, einstein.attrib)
others = einstein.find_similar()
print(len(others), [e.text for e in others][:5])
print(page.css('.quote')[1].generate_css_selector)
md = page.markdown()
print(type(md).__name__, len(md))
python similar.py

对照结果:

small {'class': 'author', 'itemprop': 'author'}
9 ['J.K. Rowling', 'Albert Einstein', 'Jane Austen',
   'Marilyn Monroe', 'Albert Einstein']
body > div > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2)
str 3019

第二行为排版折行。解读:

  • find_by_text() 找到了作者所在的 <small class="author">。
  • find_similar() 返回其余 9 个结构相同的元素,加上它自己正好是本页 10 位作者。
  • generate_css_selector 给出能定位这个元素的 CSS 选择器,可以复制到代码里用。
  • page.markdown() 把整页转成 Markdown 字符串(本页 3019 个字符),和第 2 步存 .md 文件的效果一样。

第 5 步:网页改版后,用 adaptive 把元素找回来

抓取脚本最常见的问题是网站改版,选择器全部失效。Scrapling 的自适应功能分两步:第一次抓取时加 auto_save=True,把选中元素的特征存进本地 SQLite 数据库;改版后加 adaptive=True,选择器找不到元素时,按存下的特征在新页面里找最相似的元素。

下面用两段手写 HTML 模拟改版:旧版是 ul#list 里的 li.product,新版换成了 article.item-card,id 和 class 全变了。新建 adaptive_demo.py:

from scrapling import Selector

old = '''<div class="shop"><ul id="list">
  <li class="product"><a href="/p/1">机械键盘</a><span>¥399</span></li>
  <li class="product"><a href="/p/2">降噪耳机</a><span>¥899</span></li>
</ul></div>'''

new = '''<main><section class="catalog"><div class="grid">
  <article class="item-card"><h3><a href="/p/1">机械键盘</a></h3>
    <p class="cost">¥399</p></article>
  <article class="item-card"><h3><a href="/p/2">降噪耳机</a></h3>
    <p class="cost">¥899</p></article>
</div></section></main>'''

sel = '#list li.product a'
page = Selector(old, adaptive=True, url='shop.example')
old_links = page.css(sel, auto_save=True)
print('旧版:', [a.text for a in old_links])

page = Selector(new, adaptive=True, url='shop.example')
print('新版直接选:', page.css(sel))
found = page.css(sel, adaptive=True)
print('新版 adaptive:', [(a.text, a.attrib['href']) for a in found])
rest = found[0].find_similar()
print('再找相似:', [(a.text, a.attrib['href']) for a in rest])
python adaptive_demo.py

对照结果:

旧版: ['机械键盘', '降噪耳机']
新版直接选: []
新版 adaptive: [('机械键盘', '/p/1')]
再找相似: [('降噪耳机', '/p/2')]

注意三点:

  • 两次的 url 要一致。Scrapling 按「网址 + 选择器」存取特征;不传 url 时统一记为 default,不同网站会互相覆盖。
  • 官方文档「已知问题」写明:auto_save 只保存选中结果里第一个元素的特征,所以 adaptive 只找回 1 个。实测也是如此。要拿回整组,再对找回的元素调用 find_similar(),就像最后一行。
  • 选择器本身也可以换成自定义名字:page.css(sel, auto_save=True, identifier='商品链接'),改版后用同一个 identifier 取回。

小结

  • 装 scrapling[all] 就有了抓取器、解析器、命令行和 MCP 服务器;只做 HTTP 抓取时不需要 scrapling install。
  • 不写代码时,用 scrapling extract get URL 文件.md,加 -s 选元素、加 --ai-targeted 去掉隐藏内容。
  • Fetcher.get() 抓到的页面直接用 css()、xpath() 取数据,写法和 Scrapy 一样。
  • find_by_text()、find_similar()、generate_css_selector 能帮你少写选择器。
  • auto_save 加 adaptive 让脚本扛住网站改版,但只找回第一个元素,整组要再接 find_similar()。

下一课处理 curl 拿不到内容的 JS 页面,找出页面背后的数据接口,再写一个能暂停、能续爬的爬虫。