Zillow是美国最大的房地产网站之一,提供房地产清单、房地产价格和市场分析的宝库。但是抓取 Zillow 并不容易——它的反机器人防御可以迅速关闭你的数据提取工作。
本指南将引导您了解如何使用有效抓取 Zillow 房地产数据 Massive 的住宅代理 还有剧作家的 Python。您将学习如何绕过检测、可靠地提取房地产数据,以及如何像专业人士一样扩展抓取工作流程。
为什么要抓取 Zillow 房地产数据?
Zillow 房地产数据是以下方面的金矿:
- 市场研究:分析房地产清单、定价趋势和社区统计数据,以深入了解房地产市场动态。
- 投资分析:研究历史价格模式和市场指标,以评估潜在的投资机会。
- 位置分析: 调查社区人口统计、便利设施和财产特征,以支持发展规划。
- 经济研究:监测住房市场趋势、价格指数和区域经济指标,以进行学术研究或政策研究。
无论您是数据分析师、房地产投资者还是构建自动化工具的开发人员,从Zillow抓取数据都可以为房地产市场提供宝贵的见解。
问题:Zillow 的防刮措施
由于其强大的反机器人系统,从Zillow抓取数据带来了重大挑战:
- 人工验证系统: Zillow 采用 “Press & Hold” 验证和其他方法来确认请求来自实际用户,而不是来自自动化系统。
- 速率限制: Zillow 会仔细监控页面请求的频率,如果在短时间内提出的请求过多,可能会暂时限制访问权限。
- IP 封锁: Zillow 可能会阻止来自显示异常活动模式的 IP 地址的访问。
- 动态网站更新: Zillow 定期更新其网站结构和布局,要求您的抓取工具具有适应性。
以下是当刮刀被人工验证屏蔽时会发生什么情况的示例:

这就是代理(特别是住宅代理)的用武之地。
为什么要使用代理来抓取 Zillow?
代理充当您的抓取工具和网络之间的中介。它们对于网络抓取 Zillow 至关重要,因为它们有助于:
- 避开知识产权禁令: 代理允许你 轮换 IP 地址,显著降低了被检测和封锁的风险。
- 访问受地理限制的内容:一些房地产清单和数据仅在某些地区可用。代理允许你看起来好像在不同的位置浏览。
- 绕过速率限制: Zillow 对来自单个 IP 地址的请求数量施加了限制。代理有助于将您的请求分发到多个IP上,从而使您可以避开这些限制。
但是,并非所有代理都是一样的。
住宅与数据中心代理:哪个最有效?
根据经验,住宅代理在抓取 Zillow 方面的性能优于数据中心代理。原因如下:
- 住宅代理使用与实际互联网服务提供商和设备绑定的真实 IP,使他们看起来像普通用户。
- 数据中心代理虽然更快更便宜,但很容易被Zillow的系统检测到。
如果你的目标是一致的、可扩展的无阻抓取, 住宅是必经之路。
Massive 入门
在以下地址创建您的账户 合作伙伴.joinmassive.com 并根据您的需求选择套餐。之后,转到 大型仪表板 检索您的代理凭证(用户名和密码)。

配置步骤:
请访问 快速入门 用于自定义代理设置的部分:
- 选择您的首选协议(HTTP、HTTPS 或 SOCKS5)。
- 在两者之间选择 旋转或粘性代理。
- 设置地理定位偏好(国家、州、城市、ZIP 或 ASN)。
配置完成后,您将获得适用于特定用例的即用型 cURL 命令。

有关基于位置的定位和粘性会话等高级功能,请参阅 海量文档。这些文档提供了充分利用大规模住宅代理的分步说明。
通过此设置,您可以使用大规模代理从特定区域抓取 Zillow 产品数据。
使用海量代理构建 Zillow Scraper
让我们使用以下方法构建 Zillow 刮板 剧作家 和大规模代理。Playwright 可自动进行浏览器交互并有效地处理动态内容,而代理则有助于避免检测和绕过限制。

我们将搜集房地产清单 伊利诺伊州,为每个属性提取以下信息:
- 地址
- 状态(例如 “活跃”、“待处理”)
- 价格
- 卧室数量
- 浴室数量
- 平方英尺
- 上市公司
- 房产网址
1。设置您的环境
首先创建虚拟环境并安装所需的软件包。如果愿意,你也可以使用 Conda 或 Poetry。
python -m venv zillow_envsource
zillow_env/bin/activate # Windows: zillow_env\\Scripts\\activate
pip install playwright python-dotenv
playwright install
创建一个 .env 文件以安全地存储您的海量代理凭证。
PROXY_SERVER="your_proxy_server"
PROXY_USERNAME="your_username"
PROXY_PASSWORD="your_password"
2。配置代理和浏览器设置
设置代理凭据并屏蔽不必要的资产,以优化性能并避免被发现。
class Config:
PROXY_SERVER = os.getenv("PROXY_SERVER")
PROXY_USERNAME = os.getenv("PROXY_USERNAME")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD")
BLOCKED_RESOURCES = ["stylesheet", "image", "media", "font", "imageset"]
屏蔽字体和图像等不必要的资源可加快抓取过程。
以下是资源被封锁时页面外观的示例:

3.启动支持代理的浏览器
在这里,我们定义了一个浏览器上下文,用于通过 Massive 路由请求并过滤不需要的内容。
class AsyncZillowSearchScraper:
def __init__(self, headless: bool = True):
self.headless = headless
self.playwright = None
self.browser = None
self.context = None
async def __aenter__(self):
self.playwright = await async_playwright().start()
browser_config = {"headless": self.headless}
if Config.PROXY_SERVER:
browser_config["proxy"] = {
"server": Config.PROXY_SERVER,
"username": Config.PROXY_USERNAME,
"password": Config.PROXY_PASSWORD,
}
self.browser = await self.playwright.chromium.launch(**browser_config)
self.context = await self.browser.new_context()
await self.context.route("**/*", self._route_handler)
return self
async def _route_handler(self, route):
if route.request.resource_type in Config.BLOCKED_RESOURCES:
await route.abort()
else:
await route.continue_()
4。 提取 Zillow 清单数据
Zillow 上的每个属性都包含在 <li> 标签。这些 <li> 标签有一个以 ListItem 开头的类,每个标签代表一个属性列表。里面有这些 <li> 标签,您将找到有关该物业的所有关键细节,例如地址、价格和房产特征
。

以下是这些方法 <li> 标签的结构是:
- 这个 地址 位于 <address> 用属性标记 data-test= “属性卡地址”。
- 这个 价格 在 a 之内 <span> 用属性标记 数据测试= “房产卡价格”。
诸如卧室数量、浴室数量和平方英尺之类的其他细节嵌套在其中 <ul> 清单。
以下是我们解析各个房地产清单的方法:
class ListingParser:
@staticmethod
async def extract_listing_details(listing) -> Optional[Dict]:
try:
data_container = await listing.query_selector(
'div[class*="property-card-data"]'
)
if not data_container:
return None
# Extract basic details
details = {
"address": None,
"status": None,
"price": None,
"bedrooms": None,
"bathrooms": None,
"square_feet": None,
"listing_company": None,
"url": None,
}
# Get address
if address_elem := await data_container.query_selector(
'address[data-test="property-card-addr"]'
):
details["address"] = ListingParser.clean_text(
await address_elem.text_content()
)
# Get price
if price_elem := await data_container.query_selector(
'span[data-test="property-card-price"]'
):
details["price"] = ListingParser.clean_text(
await price_elem.text_content()
)
# Get property URL
if url_elem := await data_container.query_selector(
'a[data-test="property-card-link"]'
):
if url := await url_elem.get_attribute("href"):
details["url"] = (
f"<https://www.zillow.com>{url}"
if not url.startswith("http")
else url
)
# ...
return details
except Exception as e:
logger.error(f"Error extracting listing details: {e}")
return None
5。 滚动并分页浏览结果
模拟滚动以动态加载更多列表:
async def _scroll_and_get_listings(self, page):
last_count = 0
attempts = 0
MAX_ATTEMPTS = 20
while attempts < MAX_ATTEMPTS:
listings = await page.query_selector_all('article[data-test="property-card"]')
current_count = len(listings)
if current_count == last_count:
break
last_count = current_count
await page.evaluate("window.scrollBy(0, 500)")
await asyncio.sleep(1)
attempts += 1
return listings
点击下一页 (>) 按钮浏览其他页面。

要转到下一页,请执行以下操作:
next_button = await page.query_selector('a[title="Next page"]:not([disabled])')
if next_button:
await next_button.click()
await asyncio.sleep(3)
6。 保存提取的数据
将抓取的 Zillow 数据保存到 JSON 文件中。您也可以稍后将其转换为 CSV。
class ResultsSaver:
@staticmethod
def save_results(data, filename="zillow_listings.json"):
with open(filename, "w", encoding="utf-8") as file:
json.dump(data, file, indent=4, ensure_ascii=False)
logger.info(f"Saved {len(data)} listings")
@staticmethod
def load_existing_results(filename="zillow_listings.json"):
try:
if os.path.exists(filename):
with open(filename, "r", encoding="utf-8") as file:
return json.load(file)
except Exception as e:
logger.error(f"Error loading data: {e}")
return []
7。 执行刮板
将它们整合到一个主功能中,以启动抓取器,提取数据并保存结果。
async def main():
search_url = "https://www.zillow.com/chicago-il/"
max_pages = None # Set to a number to limit pages
async with AsyncZillowSearchScraper(headless=False) as scraper:
results = await scraper.scrape_search_results(search_url, max_pages=max_pages)
print(f"\\nTotal listings scraped: {len(results)}")
if results:
print("\\nSample listing:")
print(json.dumps(results[0], indent=2, ensure_ascii=False))
if __name__ == "__main__":
asyncio.run(main())
输出示例
成功设置并使用 Massive 代理运行 Zillow 抓取工具后,输出将如下所示:
[
{
"address": "722 N Trumbull Ave, Chicago, IL 60624",
"status": "Active",
"price": "$399,000",
"bedrooms": "5",
"bathrooms": "3",
"square_feet": "2250",
"listing_company": "REMAX LEGENDS",
"url": "https://www.zillow.com/homedetails/722-N-Trumbull-Ave-Chicago-IL-60624/3810331_zpid/",
}
]
数据现已结构化且可供使用,非常适合房地产分析、仪表板或投资工具。
你可以在中使用大规模代理访问抓取 Zillow 数据的完整代码 GitHub 要点。
结论
抓取 Zillow 房地产数据可让您在了解市场、跟踪房产和建筑自动化工具方面占据优势。使用Massive的住宅代理,您可以:
- 在不被封锁的情况下抓取数据
- 定位特定的邮政编码或城市
- 实现您的 Zillow 搜索结果工作流程自动化
- 提取干净、结构化的 Zillow 房地产数据
准备好构建自己的 Zillow 数据抓取工具了吗? 注册海量代理 今天。

我是Massive的联合创始人兼首席执行官。除了在创业公司工作外,我还是一名音乐家、运动员、导师、活动主持人和志愿者。