
本文详解如何使用 scrapy 实现递归爬虫,自动定位并提取目标标题(如“az school safety program”)在全站所有出现位置的绝对 url,兼顾效率与合规性。
本文详解如何使用 scrapy 实现递归爬虫,自动定位并提取目标标题(如“az school safety program”)在全站所有出现位置的绝对 url,兼顾效率与合规性。
要精准抓取某张内容卡片(例如标题为 “AZ School Safety Program”)在整站中所有出现的页面 URL,不能仅靠单页 CSS 选择器匹配文本——因为标题本身不携带链接信息,真正需要的是承载该标题的网页地址。因此,核心思路是:逐页解析 → 检查页面内是否存在目标卡片 → 若存在,记录当前页面 URL → 再递归访问站内所有内部链接,持续探测。
以下是一个完整、可运行的 Scrapy 爬虫示例(需置于 spiders/ 目录下):
import scrapy
class PostsSpider(scrapy.Spider):
name = "card"
# 限制爬取深度,避免过度请求与服务器压力
custom_settings = {
'DEPTH_LIMIT': 1,
'DEPTH_PRIORITY': 1,
'ROBOTSTXT_OBEY': True, # 尊重 robots.txt(推荐开启)
'DOWNLOAD_DELAY': 1, # 添加延时,提升友好性
}
def start_requests(self):
# 明确起始 URL,避免默认 start_urls 机制引发的 callback 未定义错误
yield scrapy.Request(url="https://lawforkids.org", callback=self.parse)
def parse(self, response):
# 跳过非 HTML 响应(如 PDF、图片、API 接口等)
if 'text/html' not in response.headers.get('Content-Type', b'').decode():
return
# 定位所有卡片容器(根据实际 HTML 结构调整选择器)
for card in response.css("div.card-body"):
# 提取卡片标题文本,并清洗空格与换行
title = card.css("h5.card-title::text").get(default="").strip()
if title == "AZ School Safety Program":
yield {"Url": response.url} # 记录命中页面的绝对 URL
# 递归发现并跟进站内链接
for a_tag in response.css('a[href]'):
link = a_tag.css('::attr(href)').get()
if not link:
continue
absolute_link = response.urljoin(link) # 自动补全相对路径
# 仅跟进同一域名下的内部链接(防止爬出域外)
if absolute_link.startswith("https://lawforkids.org"):
yield scrapy.Request(
url=absolute_link,
callback=self.parse,
# 可选:启用优先级或去重键优化调度
# priority=10,
# dont_filter=False
)
? 关键要点说明:
- ✅
start_requests()替代start_urls:避免因未正确定义parse方法签名导致的callback is not defined错误;显式调用更可控。 - ✅ 使用
response.urljoin()处理相对 URL,确保链接绝对化,避免路径错误。 - ✅
DEPTH_LIMIT: 1是平衡覆盖率与性能的关键——实测已覆盖/programs、/officers、/educators及子路径(如/programs/lre-academy);若需更深覆盖,可谨慎增至2,但务必配合DOWNLOAD_DELAY和ROBOTSTXT_OBEY。 - ✅ 标题比对采用
.strip()清洗空白符,提升匹配鲁棒性;如需模糊匹配(如含大小写/标点差异),可用re.search(r'az.*school.*safety.*program', title, re.I)替代严格相等。 - ⚠️ 切勿省略
ROBOTSTXT_OBEY和合理延迟——这是负责任爬虫的基本准则,也是避免被封禁的前提。
运行命令:
scrapy crawl card -o results.jsonl
输出为 JSONL 格式,每行一个匹配结果,便于后续清洗与分析。
最终,你将获得一份结构清晰、来源可信的全站卡片分布清单,彻底替代人工排查,高效支撑内容审计、SEO 分析或知识图谱构建等场景。










