使用海量代理抓取 Zillow 房地产数据,笔记本电脑和服务器处于云端数据背景。”

如何使用 Massive 抓取 Zillow 数据-新手指南

Jason Grad
创始人
March 28, 2025

準備好測試高級代理的效能了嗎?

使用海量代理抓取 Zillow 房地产数据,笔记本电脑和服务器处于云端数据背景。”

如何使用 Massive 抓取 Zillow 数据-新手指南

Jason Grad
创始人
March 28, 2025

Zillow是美国最大的房地产网站之一,提供房地产清单、房地产价格和市场分析的宝库。但是抓取 Zillow 并不容易——它的反机器人防御可以迅速关闭你的数据提取工作。

本指南将引导您了解如何使用有效抓取 Zillow 房地产数据 Massive 的住宅代理 还有剧作家的 Python。您将学习如何绕过检测、可靠地提取房地产数据,以及如何像专业人士一样扩展抓取工作流程。

为什么要抓取 Zillow 房地产数据?

Zillow 房地产数据是以下方面的金矿:

  • 市场研究:分析房地产清单、定价趋势和社区统计数据,以深入了解房地产市场动态。
  • 投资分析:研究历史价格模式和市场指标,以评估潜在的投资机会。
  • 位置分析: 调查社区人口统计、便利设施和财产特征,以支持发展规划。
  • 经济研究:监测住房市场趋势、价格指数和区域经济指标,以进行学术研究或政策研究。

无论您是数据分析师、房地产投资者还是构建自动化工具的开发人员,从Zillow抓取数据都可以为房地产市场提供宝贵的见解。

问题:Zillow 的防刮措施

由于其强大的反机器人系统,从Zillow抓取数据带来了重大挑战:

  • 人工验证系统: Zillow 采用 “Press & Hold” 验证和其他方法来确认请求来自实际用户,而不是来自自动化系统。
  • 速率限制: Zillow 会仔细监控页面请求的频率,如果在短时间内提出的请求过多,可能会暂时限制访问权限。
  • IP 封锁: Zillow 可能会阻止来自显示异常活动模式的 IP 地址的访问。
  • 动态网站更新: Zillow 定期更新其网站结构和布局,要求您的抓取工具具有适应性。

以下是当刮刀被人工验证屏蔽时会发生什么情况的示例:

这就是代理(特别是住宅代理)的用武之地。

为什么要使用代理来抓取 Zillow?

代理充当您的抓取工具和网络之间的中介。它们对于网络抓取 Zillow 至关重要,因为它们有助于:

但是,并非所有代理都是一样的。

住宅与数据中心代理:哪个最有效?

根据经验,住宅代理在抓取 Zillow 方面的性能优于数据中心代理。原因如下:

  • 住宅代理使用与实际互联网服务提供商和设备绑定的真实 IP,使他们看起来像普通用户。
  • 数据中心代理虽然更快更便宜,但很容易被Zillow的系统检测到。

如果你的目标是一致的、可扩展的无阻抓取, 住宅是必经之路

Massive 入门

在以下地址创建您的账户 合作伙伴.joinmassive.com 并根据您的需求选择套餐。之后,转到 大型仪表板 检索您的代理凭证(用户名和密码)。

配置步骤:

请访问 快速入门 用于自定义代理设置的部分:

  1. 选择您的首选协议(HTTP、HTTPS 或 SOCKS5)。
  2. 在两者之间选择 旋转或粘性代理。
  3. 设置地理定位偏好(国家、州、城市、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 数据抓取工具了吗? 注册海量代理 今天。

作者简介
Jason Grad
创始人

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

经常问的问题

+

+

+

+

+

+

+

+

+

+

Ready to test premium proxy performance?