Python 版 Craigslist 抓取工具:分步指南

Craigslist 仍然运行在纯 HTML 上,没有沉重的 JavaScript 应用墙,也没有无休止的登录提示。这使得它 对任何人来说最容易上手的网站之一 第一次学习抓取 Craigslist。但“易上手”并不意味着“没有规则”。在速率限制、不断变化的页面标记,以及 Craigslist 自身对自动化访问的立场之间,一个 Python Craigslist 抓取工具需要比基础教程脚本多一些谨慎。
本指南将逐步讲解 从零开始构建一个真正的 Craigslist 抓取器 Python 项目。你将编写自己的 Requests 和 BeautifulSoup 代码,从页面中提取标题、价格、地点和 URL,并将所有内容导出到一个整洁的 CSV 文件中。在此过程中,我们将讨论人们在开始抓取 Craigslist 之前总会问到的法律问题,以及当你的请求开始被封锁时该怎么办。
为什么要抓取 Craigslist?
Craigslist 是互联网上最大的未经过滤的实时分类信息来源之一。在你和实际发布的帖子之间没有任何聚合平台作为中间层。
人们构建爬虫最常见的一些原因:
- 市场调研 ——追踪某个地区内正在出售什么、在哪里出售以及售价多少
- 租房监测 ——一个巨大的应用场景是抓取 Craigslist 的房源列表,以便在新公寓刚发布的那一刻就捕捉到它们,赶在它们被抢走之前
- 二手车调研 — 比较特定品牌和型号在各个城市的报价
- 价格跟踪 — 连续几周或几个月观察某个分类以发现趋势
- 竞品分析 — 卖家查看其细分领域中类似商品的定价
一个每隔几个小时抓取一次搜索结果页面的简单脚本,就能独立回答这些问题中的大多数。
抓取 Craigslist 合法吗?
这取决于你抓取什么、如何访问它,以及之后如何处理这些数据。这里的任何内容都不构成法律建议。如果你正在构建某种商业项目,请咨询真正的律师,并阅读 Craigslist 的使用条款 你自己。
Craigslist 关于自动化抓取的使用条款
Craigslist 的使用条款 禁止自动化数据采集。它们涵盖了机器人、脚本和其他自动化工具,明确表明不允许批量数据采集。尽管许多开发者都在抓取 Craigslist。请注意,即使在技术上可行,这样做也可能违反该网站的使用条款。
Robots.txt
Craigslist 的 robots.txt 文件规定了自动化爬虫应当避开哪些区域,包括用于回复列表和其他内部功能的页面。遵守 Craigslist 的 robots.txt 抓取政策体现了负责任的做法,尽管 robots.txt 本身并不具有法律约束力。它也反映了该网站限制自动化访问的意图。
Craigslist 数据抓取诉讼
Craigslist 已对以下公司采取了法律行动 大规模抓取房源并将数据用于商业目的进行再发布。这些案件针对的是大型企业,而非采集少量数据的个人。如果你打算抓取 Craigslist,请查阅该网站的使用条款,并避免将抓取到的内容用于商业用途。
你需要的工具
本项目使用一套简短、标准的 Python 技术栈。这里的所有内容都不需要付费许可或复杂的安装过程。
- Python 3.9+ — 任何近期版本都能正常使用
- Requests 库 — 负责处理 HTTP 请求和请求头管理
- BeautifulSoup — 将返回的 HTML 解析为可供查询的结构
- lxml — 一个快速的解析器后端,BeautifulSoup 可以用它来替代 Python 内置的解析器
- csv — Python 标准库的一部分,用于写出结果
- NodeMaven 住宅代理 — 可选,但当你定期运行抓取程序或跨多个城市运行时,它能帮你避免 IP 被标记,因此非常有用
相关阅读: 用 Python 进行网页抓取:完整指南
理解 Craigslist 的 HTML 结构
在编写任何解析代码之前,先了解你实际要解析的内容会很有帮助。一个 Craigslist 搜索结果页(例如某个城市的公寓房源列表页)是由一系列重复的房源卡片构成的。 每张卡片都是一个 HTML 列表项,其中包含:
- 一个链接元素 其中包含该房源的标题文本及其完整 URL
- 价格值(当帖子附带坐标时)
- 社区或区域 大致标示该物品所在位置的标签
每一张列表卡片都遵循相同的重复模式,这正是 Craigslist 可以用 CSS 选择器抓取的原因。你先找到一张卡片,看看它是如何标记的,然后告诉 BeautifulSoup“帮我找出所有看起来像这样的元素”。
棘手之处在于,Craigslist 会随着前端的更新,定期更改其类名和标记。 今天有效的选择器,六个月后可能什么都返回不了。这对于抓取任何网站来说都很正常,也正因如此,下面的代码在某个字段缺失时会优雅地失败并打印一条警告,而不是直接崩溃。
用 Python 构建 Craigslist 抓取工具
这是本指南的核心部分。我们会分成一个个小步骤来构建这个抓取器,让每一部分都易于理解,然后再把它们整合成一个完整的脚本。
第 1 步:安装依赖项
打开终端,安装本项目所需的两个外部包:
Requests 库 负责处理网络请求。 BeautifulSoup 负责解析 HTML。 lxml 是我们将交给 BeautifulSoup 的解析器引擎,因为它明显比默认解析器更快。
第 2 步:发送 HTTP 请求
这里有几点值得注意。 User-Agent 请求头是这类请求中最重要的一个请求头。如果没有它,包括 Craigslist 在内的许多服务器要么会返回精简后的响应,要么会直接屏蔽该请求。而 代理 参数是可选的,默认保持为空。
第 3 步:解析 HTML
这一步刻意保持简单。它所做的只是把文本交给 BeautifulSoup,然后返回一个树状结构,你可以用 CSS 选择器在其中进行搜索,就像你在样式表中定位元素那样。
第 4 步:提取房源数据
这里就是真正的抓取逻辑所在。Craigslist 会把每条结果包裹在一个列表项中,而我们会抓取页面上的每一个列表项。
请注意这里的回退处理。 该函数并不假设某个选择器始终能够匹配,而是在第一个选择器返回空结果时,尝试第二个更宽松的匹配模式。这是一个小习惯,当网站的标记结构发生变化时能省下大量调试时间。
第 5 步:提取标题、价格、位置和 URL
每个字段都独立提取,并默认采用安全的回退值,而不是抛出错误。 这一点很重要,因为真实的房源页面往往杂乱无章:有些帖子没有价格,有些没有明确的位置标签,而一个在遇到第一个缺失字段时就崩溃的脚本,对于任何你打算无人值守运行的任务来说都毫无用处。
第 6 步:导出为 CSV
csv.DictWriter 会自动将每个字典的键与表头行匹配,因此只要每个房源字典都有相同的四个键,这就能正常工作。
整合到一起
直接运行该文件,它就会抓取一个搜索页面,提取出所能找到的每一条房源,将前五条打印到你的终端,并把完整数据集写入 craigslist_listings.csv。从这里开始,你可以遍历多个分类或城市的 URL,通过跟随页面上的“下一页”链接来实现分页,或者将脚本安排为定时运行,以便持续跟踪价格或租金。
重要: Craigslist 的标记结构会时不时地发生变化。如果 find_listing_cards() 突然返回空列表时,请在浏览器中打开搜索页面,检查某个房源卡片,并更新第 4 步中的选择器以匹配你所看到的内容。
抓取 Craigslist 时避免被封锁
一旦你的请求量超过了少数几次测试请求,被封锁就会成为真正的瓶颈。Craigslist 并未公布确切的速率限制,但从单个 IP 发送请求过快,是最快让你开始看到空白页面的方式。
一些好习惯能带来很大帮助:
- 在请求之间添加延迟。在每次加载页面之间间隔几秒钟,比紧密循环更能模拟正常的浏览行为。
- 内置带退避的重试机制,这样单个失败的请求就不会毁掉整个抓取任务。
- 轮换 IP 当你发出大量请求时尤其如此。单个 IP 反复猛烈访问同一个搜索页面会格外显眼。
- 设置真实的请求头,不仅仅是 User-Agent,在合理的情况下还包括 Accept-Language 和 Referer。
- 遵守速率限制 即便这些限制没有公布出来,一旦你发现错误比平时多,就要放慢速度。
住宅代理 可以通过将请求路由经过真实的家庭 IP 地址(而非容易被识别的数据中心 IP)来提升抓取的可靠性。NodeMaven 的代理非常适合 Craigslist 抓取,而 移动代理 对于同时涉及账户管理的工作流程也很有用。

在运行抓取程序之前,你可以用 NodeMaven 的免费工具来验证你的配置。 带宽检测工具 测试代理连通性, IP Lookup 工具 确认网站所看到的 IP 和位置。
Craigslist 抓取 API 与 Python 抓取工具对比
Craigslist 没有针对搜索结果的官方公开 API,这也是为什么这么多人最终选择自己编写工具的部分原因。这就留下了几种现实可行的路径,每一种在投入精力和控制程度之间都有着不同的权衡。
| 方法 | 配置工作量 | 灵活性 | 最适合 |
| Requests + BeautifulSoup | 低 | 对于静态页面较高 | 搜索页面、简单的数据抓取、学习型项目 |
| Scrapy | 中 | 高,专为规模化而构建 | 大规模、持续、多页面的爬取 |
| Selenium | 中高 | 完整的浏览器控制 | 需要 JavaScript 渲染或交互的页面 |
| 第三方抓取 API | 非常低 | 受限于服务商所支持的范围 | 快速原型开发、非开发人员 |
由于 Craigslist 的搜索页面是在服务器端渲染的,展示列表信息并不需要 JavaScript,因此 Requests 和 BeautifulSoup 通常是最简单也最快的方案,这正是我们在本指南中围绕它们来构建抓取器的原因。
常见的 Craigslist 抓取错误
一旦你真正运行一个爬虫,而不是仅仅针对单个测试页面,就会不断出现一些错误。
- 403 Forbidden 通常是因为缺失或可疑的 User-Agent 请求头,或者是一个已经被标记的 IP。先仔细检查你的请求头,然后再考虑轮换 IP。
- 429 请求过多 你发送请求的速度超过了服务器愿意响应的速度。增加延迟并放慢你的循环。
- CAPTCHA 验证挑战 ——这表明你的流量模式看起来像是自动化的。降低请求速率和轮换 IP 都有助于减少触发的频率。
- 空响应 ——有时服务器会返回有效的 200 状态码,但页面没有任何实际内容,这通常是一种软封锁。在断定你的解析器出问题之前,先检查一下原始 HTML 的长度。
- 选择器缺失 — 你的解析代码没有返回任何内容,但请求本身运行正常。这几乎总是意味着 Craigslist 更改了它的类名;请手动检查页面并更新你的选择器。
其他抓取框架
Requests 和 BeautifulSoup 能满足大多数 Craigslist 抓取需求,但了解一下其他替代方案也是值得的。
Scrapy 是一个完整的抓取框架,内置请求调度、重试机制以及用于导出数据的管道。当一个项目从单个脚本发展成需要按计划跨多个页面运行时,它是更合适的选择。
Selenium 驱动一个真实的浏览器,这对于那些在页面加载后用 JavaScript 构建内容的网站很重要。Craigslist 的搜索结果不需要这一点,但如果你以后扩展到需要这类功能的网站,它就是合适的工具。
Playwright 是 Selenium 的一个较新替代方案,用途类似:完整的浏览器自动化,通常在现代多标签或多上下文抓取场景中更快、更易于使用。
结论
现在你已经拥有了一个可用的 Craigslist 数据爬虫: 它会发送一个带有正确请求头的请求,解析返回的 HTML,为页面上的每一条列表提取标题、价格、位置和 URL,并将结果写入 CSV。无论你是在追踪租房价格、研究二手车列表,还是长期关注某个特定类别,这都是一个坚实的基础。
这里法律和技术两方面都很重要。阅读 Craigslist 的使用条款,把请求量保持在合理范围内,并把 robots.txt 当作一个值得尊重的信号,即使它并未涵盖你感兴趣的所有内容。
当你的抓取工作从少数几次手动运行,发展到定时任务或多城市数据拉取时,IP 轮换就不再是可有可无的了。到了这个阶段,代理便在你的技术栈中占有一席之地。


