# 如何抓取Zillow房地产数据：搜索JSON、Zestimate、PerimeterX

Zillow将其列表数据作为JSON隐藏在页面中——你不需要解析任何一个div。以下是如何驱动地图边界搜索API、突破分页限制并应对PerimeterX的方法。

Zillow拥有超过**1.1亿个房产**，每月吸引大约**2.45亿访客**，这使其成为美国房地产数据的默认来源——价格、地址、卧室、浴室、zestimates和租金估算。它也位于PerimeterX之后并在客户端渲染，因此简单的抓取器会得到403和一个空白页面。好消息是：如果你知道在哪里找，Zillow会以JSON的形式提供其数据，并且其搜索是由你可以直接调用的地图坐标驱动的。以下是整个方法。

## 不要解析HTML——Zillow提供JSON

在Zillow的房产页面上不需要与CSS选择器斗争。完整的房产记录作为隐藏的网页数据嵌入在script标签中。两个位置几乎涵盖了每个页面：`<script id="__NEXT_DATA__">`包含Next.js缓存，而有些页面则使用`<script id="hdpApolloPreloadedData">`（Apollo GraphQL缓存）。抓取任意一个，解析它，你就拥有一个干净的对象，包含`zpid`、`price`、`livingArea`、`bedrooms`、`bathrooms`、`latLong`、`homeStatus`、`rentZestimate`等信息：

```python
import json, re, requests

proxy = "http://USER:PASS@residentialpremium.quantumproxies.io:8080"
proxies = {"http": proxy, "https": proxy}
HEADERS = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
           "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36",
           "accept-language": "en-US,en;q=0.9"}

def property_json(url):
    r = requests.get(url, headers=HEADERS, proxies=proxies, timeout=20)
    r.raise_for_status()                       # 403 => blocked, rotate IP
    m = re.search(r'id="__NEXT_DATA__"[^>]*>(.*?)</script>', r.text, re.S)
    if m:
        data = json.loads(m.group(1))
        cache = data["props"]["pageProps"]["componentProps"]["gdpClientCache"]
        return next(iter(json.loads(cache).values()))["property"]
    # fallback: Apollo cache
    m = re.search(r'id="hdpApolloPreloadedData"[^>]*>(.*?)</script>', r.text, re.S)
    cache = json.loads(json.loads(m.group(1))["apiCache"])
    return next(v["property"] for k, v in cache.items() if "ForSale" in k)
```

嵌入的记录比可见页面丰富得多。除了价格和地址，你还可以获得`zestimate`和`rentZestimate`——Zillow自己的销售和租赁估值——以及`homeStatus`（在售、已售、出租）、`daysOnZillow`、地块和居住面积，以及精确的纬度和经度。这些信息足以满足比较模型、潜在客户评分管道或市场仪表板的需求，每个房产以一个干净的JSON对象提供，而不是一打容易在下次重新设计时失效的CSS选择器。

## 搜索API运行在地图坐标上

Zillow的搜索不是以关键词为主，而是以地图为主。在后台，提交搜索会向`zillow.com/async-create-search-page-state`发送一个请求，其中包含一个核心字段为`mapBounds`的`searchQueryState`对象：四个数字（北、南、东、西）在地图上画出一个矩形。给它一个边界框，它会返回其中的每个列表，作为结构化的JSON：

```python
def search_area(bounds, page=1):
    url = "https://www.zillow.com/async-create-search-page-state"
    body = {
        "searchQueryState": {
            "pagination": {"currentPage": page},
            "mapBounds": bounds,   # {'north':..,'south':..,'east':..,'west':..}
            "filterState": {"sortSelection": {"value": "days"}},
        },
        "wants": {"cat1": ["listResults", "mapResults"], "cat2": ["total"]},
        "requestId": 2,
    }
    r = requests.put(url, json=body, headers=HEADERS, proxies=proxies, timeout=20)
    return r.json()["cat1"]["searchResults"]["listResults"]

# New Haven, CT bounding box
listings = search_area({"north": 41.366, "south": 41.230,
                        "east": -72.827, "west": -73.030})
```

![按地图坐标搜索 Zillow：画出一个 mapBounds 框，以 JSON 发送用于 listResults 的搜索状态，使用美国住宅出口让 PerimeterX 保持安静，再拆分成象限以突破结果上限；卡片显示了康涅狄格州纽黑文（New Haven, CT）的框：北 41.366，南 41.230，东 -72.827，西 -73.030。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335180/blog/generated/qp-b9-045-diag1.png)
*通过地图坐标驱动Zillow：边界框是查询，住宅IP保持PerimeterX安静。*

## 突破820结果上限

Zillow仅分页20页，每页约41项，因此单个搜索最多约**820个结果**，无论该地区有多少房屋。密集市场隐藏了更多的房源。解决方法是递归象限分割：如果一个边界框返回最大页数，将其分割为四个更小的框并分别搜索；继续细分，直到每个框返回的结果少于上限。这种放大策略可以从一个大都市中挖掘出成千上万的列表，而平面搜索永远不会显示——而且它只在密度需要时细分，因此你不会在空旷的乡村浪费请求。

这种彻底性的代价是：每次细分都会增加请求，因此一个密集的大都市可以将一次搜索变成几十次。为此做好预算——限制递归深度，并仅在结果数量证明其合理时放大，算法通过仅在一个框仍达到最大页数时细分来为你做到这一点。对于一个城市的每晚更新，大多数请求会落在少数密集的市中心框上，而郊区则在一次通过中解决，因此你只在库存所在的地方花费深度，而不是其他地方。

## PerimeterX是简单抓取器失败的原因

Zillow的阻止主要不是基于速率；而是PerimeterX（现为HUMAN）对请求进行分析。数据中心IP、缺少浏览器头和不人性化的时间安排都会触发403或挑战——这就是`assert status == 200`真正检查的内容。解决方法是一个一致、可信的请求：[美国住宅代理](https://quantumproxies.io/residential-proxies)使出口IP看起来像购房者，现实的浏览器头，以及在任何403时旋转到一个新的IP而不是重试已被封锁的IP的指数退避。我们对[PerimeterX如何检测自动化](https://quantumproxies.io/blog/how-perimeterx-human-detects-automation-in-2026)的分解深入探讨了这些信号；同样的姿态适用于[使用相同供应商的Walmart](https://quantumproxies.io/blog/scrape-walmart-product-data)。

当PerimeterX收紧或你不想维护一个浏览器群时，[Scraper API](https://quantumproxies.io/scraper-api)为你渲染页面，旋转住宅IP并清除挑战，返回相同的隐藏JSON而无需操作开销。

[通过住宅IP在PerimeterX后抓取Zillow](https://quantumproxies.io/residential-proxies)

![Zillow 收录了超过 11000 万套房产，每月吸引约 24500 万访客，但一次不分区的搜索在 820 条结果处就会停止，即 20 页、每页约 41 条；递归的象限拆分只细分密集区域，就能在一个大都市区覆盖数十万条房源。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335180/blog/generated/qp-b9-045-diag2.png)
*规模巨大，但一次搜索限制在820——围绕这一上限进行工程才是真正的工作。*

## 何时使用县记录

Zillow在列表、照片和估算方面表现出色，但它是一个次要来源。对于权威的所有权、销售历史和评估价值，县评估员和记录员办公室发布公共记录——通常通过他们自己的门户或批量数据导出。如果你的用例是产权、比较或税务数据而不是实时列表，县级记录更清晰、收集更宽松，并且完全没有PerimeterX的限制。使用Zillow获取市场信号，使用县记录获取真实数据。

## 抓取Zillow是否合法？

这是一般信息，而非法律建议。公开可用的列表数据——价格、地址、房产属性——通常被认为可以以尊重的速度收集。然而，Zillow的结果可能包含个人数据：代理姓名、电话号码和经纪人详细信息。这些信息受GDPR和类似法律保护，因此在没有合法依据的情况下，避免收集和存储这些信息。收集房产事实，而不是个人信息。

## 常见问题解答

### 我可以抓取Zillow数据吗？

可以——公开可见的列表数据可以被收集。Zillow将每个房产记录嵌入在一个script标签（`__NEXT_DATA__`或Apollo缓存）中，并且其搜索运行在一个你可以直接调用的地图边界API上。障碍不是访问而是PerimeterX，因此你需要住宅IP和一致的头以避免403。

### Zillow有API吗？

Zillow提供大约20个官方API，包括房产详情和社区数据，但它们需要密钥、有使用限制，并且不涵盖每个字段或批量使用案例。许多团队选择抓取公共页面，正是因为隐藏的JSON已经包含了他们需要的价格、卧室、浴室、面积、zestimate和租金估算。

### 为什么我的Zillow抓取器会得到403？

Zillow上的403几乎总是PerimeterX，而不是速率限制。数据中心IP、缺失或不一致的浏览器头以及机器人的请求时间都会触发它。切换到美国住宅代理，发送真实的头，添加类似人类的间隔，并在每次403时使用指数退避旋转到一个新IP，而不是反复尝试被封锁的IP。

### 如何从一个地区抓取超过820个Zillow列表？

单个搜索限制在约820个结果（20页41项）。要深入挖掘，将地图边界框分为四个象限并分别搜索；递归细分任何仍达到上限的象限。这种放大方法仅细分密集区域，因此它捕获一个大都市的完整库存，而不会在稀疏地区浪费请求。

跳过HTML并读取嵌入的JSON，通过地图边界驱动搜索，分割象限以突破上限，并通过干净的住宅IP路由所有内容，以保持领先于PerimeterX。做到这一点，Zillow就成为一个结构化的房地产信息源，而不是403的墙。

[在不与PerimeterX斗争的情况下获取Zillow JSON](https://quantumproxies.io/scraper-api)
