# 如何抓取Craigslist列表：车辆、租赁和兼职

Craigslist是一个数据宝库，但受到严格的IP速率限制。这里是每个城市的URL结构、每页120条的分页数学、许多人忽略的RSS快捷方式，以及让你不被封禁的代理设置。

Craigslist拥有大量可用的公共数据——二手车、公寓租赁、兼职、待售物品、服务——分布在数百个城市网站上。对于初学者来说，它也是CAPTCHA和IP封禁的障碍，因为Craigslist对IP地址进行严格的速率限制。好消息是：网站的URL结构简单且可预测，有一个大多数指南都跳过的RSS快捷方式，封禁问题几乎完全是IP卫生问题。本指南涵盖了每个城市的URL模式、分页数学、解析、RSS路径和保持抓取器不被封禁的代理设置。用于个人或研究用途时，请遵守Craigslist的条款，并将此视为一般信息而非法律建议。

## URL模式是整个游戏的关键

Craigslist按城市子域和类别代码划分，其他都是查询参数。学会一次，就可以针对任何城市和板块：`https://{city}.craigslist.org/search/{category}?query={q}`。类别代码很短——`sss`代表所有待售物品，`cto`代表车主出售的车辆，`apa`代表公寓，`ggg`代表兼职。添加`min_price`、`max_price`和其他过滤器作为参数。分页使用`s`参数，每页显示120个结果——所以第二页是`s=120`，第三页是`s=240`，以此类推。

```python
import requests
from bs4 import BeautifulSoup

PROXY = "http://USER:PASS@residentialpremium.quantumproxies.io:8080"
PROXIES = {"http": PROXY, "https": PROXY}
UA = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
      "(KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36")

def build_url(city, category, query, page=0, min_price=None, max_price=None):
    base = f"https://{city}.craigslist.org/search/{category}"
    params = [f"query={query}"]
    if min_price: params.append(f"min_price={min_price}")
    if max_price: params.append(f"max_price={max_price}")
    if page:      params.append(f"s={page * 120}")   # 120 results per page
    return base + "?" + "&".join(params)

url = build_url("minneapolis", "cto", "bmw", page=0, max_price=8000)
r = requests.get(url, headers={"User-Agent": UA}, proxies=PROXIES, timeout=20)
```

## 解析列表

搜索结果行标记有一组稳定的类——列表块是`.result-info`，内部有`.result-title`、`.result-price`和`.result-date`。保护每个字段，因为并不是每个列表都有价格：

```python
def parse_listings(html):
    soup = BeautifulSoup(html, "html.parser")
    out = []
    for row in soup.select(".result-info"):
        title_el = row.select_one(".result-title")
        price_el = row.select_one(".result-price")
        date_el  = row.select_one(".result-date")
        if not title_el:
            continue
        out.append({
            "title": title_el.get_text(strip=True),
            "url":   title_el.get("href"),
            "price": price_el.get_text(strip=True) if price_el else None,
            "date":  date_el.get("datetime") if date_el else None,
        })
    return out

listings = parse_listings(r.text)
print(len(listings), "listings on this page")
```

对于更丰富的记录——如车辆的里程数、租赁的卧室数——请跟随每个列表URL并解析详细页面。这会使请求数量翻倍，因此正是节奏和轮换开始重要的地方。

![拆解为各部分的 Craigslist 搜索 URL：minneapolis 城市子域名、cto 类别代码、query 和 max_price 筛选参数，以及 s 偏移量；卡片逐一解释：城市子域名，类别代码 sss、cto、apa 和 ggg，筛选参数，以及以 120 为步长的翻页。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335182/blog/generated/qp-b9-048-diag1.png)
*Craigslist URL是完全可预测的：城市子域、类别代码，然后是查询和120步的s参数。*

## 大多数指南跳过的RSS快捷方式

Craigslist没有通用的公共API，但它确实为搜索结果提供了一个RSS订阅——在任何搜索URL后附加`&format=rss`，你就会得到一个结构化的XML订阅，而不是需要解析的HTML。它更轻，不太可能触发反机器人启发式算法，比反复加载完整结果页面更理想，适合监控：按计划轮询保存的搜索并对比新项目。它返回的字段比HTML页面少（标题、链接、时间戳），所以用于新鲜度监控，当需要价格和详细信息时再回到HTML。

```python
import feedparser

# Any Craigslist search becomes a feed with &format=rss
feed_url = build_url("sfbay", "apa", "loft", max_price=3500) + "&format=rss"
raw = requests.get(feed_url, headers={"User-Agent": UA}, proxies=PROXIES, timeout=20)
feed = feedparser.parse(raw.content)

for entry in feed.entries[:5]:
    print(entry.updated, entry.title, entry.link)
```

## Craigslist为何封禁你，以及如何避免被封禁

Craigslist堆叠了几种防御措施，但它们共享一个根本：它跟踪每个IP地址的请求，并封禁过于频繁的地址。具体措施包括IP速率限制、对可疑流量的CAPTCHA挑战、User-Agent监控、会话跟踪和临时IP封禁。每一个都可以通过看起来像许多普通访客而不是一个不懈的机器来击败。

- **轮换IP并分散负载**——单个IP在一个城市分页是最快的封禁途径。每个请求轮换一个住宅池意味着没有出口看起来异常。
- **控制请求节奏**——每秒1-2个请求是小规模运行的安全上限；添加抖动，一旦看到CAPTCHA或403就立即退避。
- **轮换User-Agent**——一个恒定或默认的UA是个标志；改变它并保持最新。
- **每个城市一个会话**——每个城市或每次运行开始新的cookie，而不是将一个身份带到所有地方。

因为封禁是基于IP的，出口IP做了大部分工作。一个干净的[住宅代理](https://quantumproxies.io/residential-proxies)池看起来像真实的家庭连接，每个请求轮换分散多城市抓取，以至于Craigslist的每IP计数器从未触发。如果你在多个城市收集，我们的[修复429速率限制](https://quantumproxies.io/blog/fix-429-too-many-requests-scraping)指南涵盖了节奏和并发预算方面，[反封禁清单](https://quantumproxies.io/blog/avoid-ip-ban-web-scraping)将其全部结合在一起。

[在干净的住宅IP上抓取Craigslist](https://quantumproxies.io/residential-proxies)

## 跨城市扩展

Craigslist数据的真正力量在于跨城市比较——相同的二手车或租赁在多个大都市的定价。循环你的城市列表，为每个城市绑定一个新的轮换出口，限制并发，并将城市与每条记录一起存储。对于车辆和租赁研究，使用相同的模式来提供比较管道；参见我们的[抓取汽车列表](https://quantumproxies.io/blog/scrape-car-listings-autotrader-carscom)和[房地产数据](https://quantumproxies.io/blog/real-estate-data-scraping-with-proxies)指南，将原始列表转化为市场信号。

![不同配置下的 Craigslist 封禁风险：用单个 IP 翻遍一个城市的页面最快被封，使用固定 User-Agent 的数据中心 IP 会遇到 CAPTCHA 或 403，以每秒 1-2 个请求轮换住宅出口则从不触发限制；卡片列出了解决方法，从每个请求轮换 IP 到每个城市使用新会话。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335183/blog/generated/qp-b9-048-diag2.png)
*每个Craigslist防御都是IP和节奏问题——轮换住宅出口并保持每秒1-2个请求以下。*

## 常见问题解答

### 你能抓取Craigslist吗？

是的——公共搜索和列表页面是可以抓取的，Craigslist甚至为搜索提供了一个RSS订阅。障碍是激进的每IP速率限制，而不是解析。轮换住宅IP，将请求控制在每秒1-2个，你可以可靠地收集车辆、租赁、兼职和待售数据。尊重Craigslist的条款，只抓取公共数据。

### Craigslist有API吗？

没有通用的公共数据API，但每个搜索URL可以通过附加`&format=rss`返回一个RSS订阅。这为你提供了一个结构化的XML订阅，包含标题、链接和时间戳——非常适合监控新列表——而HTML页面则包含更完整的字段，如价格和描述。

### 如何避免抓取Craigslist时被IP封禁？

Craigslist通过IP速率封禁，因此解决方案都是关于分散和减缓负载：每个请求轮换住宅IP，保持每秒1-2个请求并添加抖动，轮换你的User-Agent，每个城市使用一个新的会话，一旦看到CAPTCHA或403立即退避。一个数据中心IP猛击一个城市最快被封禁。

### Craigslist的分页如何工作？

Craigslist每页显示120个结果，并使用`s`查询参数作为偏移进行分页。第一页省略`s`，第二页是`s=120`，第三页是`s=240`，以此类推。以120的步长递增，直到某页返回少于120个结果，这标志着结束。

Craigslist易于阅读且易于被封禁——而第二个问题完全是关于IP卫生。掌握URL模式，使用RSS进行监控，以120的步长分页，并以人类的速度通过轮换的住宅IP路由所有内容。这样做，CAPTCHA就会停止出现。

[从轮换的住宅代理开始](https://quantumproxies.io/residential-proxies)
