第 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 在模拟改版后找回元素。
课程目录第 1 / 3 课
学习位置仅保存在当前浏览器,有效期 180 天。
图文教材
本课对照的官方页面:安装、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 页面,找出页面背后的数据接口,再写一个能暂停、能续爬的爬虫。
