You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Selenium爬取Zillow租房数据时分页重复显示问题求助

解决Zillow翻页后房源数据重复的问题

核心问题原因

Zillow的房源列表是动态加载的——点击下一页后页面不会整体刷新,只是通过AJAX替换房源区域的内容。如果点击后立刻抓取数据,大概率会读到DOM里还没更新的旧内容;或者你的代码一开始就定位了房源元素,之后没重新获取,导致一直读取第一页的缓存元素。

具体解决方案

1. 必须等待新内容加载完成

点击下一页后,不要急着爬数据,先等页面内容更新。可以用这几种方式判断:

  • 等待当前页码的文本变化(比如从"1"变成"2")
  • 等待旧的房源元素失效(DOM里被移除)
  • 等待房源列表的元素数量/内容更新

示例代码片段:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# 点击下一页按钮
next_btn = driver.find_element(By.CSS_SELECTOR, "button[aria-label='Next page']")
next_btn.click()

# 等待第一页的第一个房源元素失效(确保新内容加载)
first_old_listing = driver.find_element(By.CSS_SELECTOR, "div[data-testid='property-card']")
WebDriverWait(driver, 10).until(EC.staleness_of(first_old_listing))

# 现在重新获取最新的房源列表
listings = driver.find_elements(By.CSS_SELECTOR, "div[data-testid='property-card']")

2. 每次翻页后重新定位房源元素

绝对不要复用一开始获取的listings对象,每次翻页后都要重新调用find_elements抓取最新的DOM元素。

错误示范(会一直读第一页):

# 只在开头获取一次房源列表
listings = driver.find_elements(By.CSS_SELECTOR, "div[data-testid='property-card']")
for page in range(5):
    # 处理listings,然后翻页
    next_btn.click()
    # 这里的listings还是第一页的内容

正确示范:

for page in range(5):
    # 每次循环都重新获取当前页的房源
    listings = driver.find_elements(By.CSS_SELECTOR, "div[data-testid='property-card']")
    for listing in listings:
        # 提取数据
        price = listing.find_element(By.CSS_SELECTOR, "span[data-testid='property-card-price']").text
        address = listing.find_element(By.CSS_SELECTOR, "address[data-testid='property-card-addr']").text
        link = listing.find_element(By.CSS_SELECTOR, "a[data-testid='property-card-link']").get_attribute("href")
        # 保存数据
    # 翻页并等待加载
    try:
        next_btn = driver.find_element(By.CSS_SELECTOR, "button[aria-label='Next page']")
        if next_btn.is_enabled():
            next_btn.click()
            # 等待页码更新为下一页
            WebDriverWait(driver, 10).until(
                EC.text_to_be_present_in_element((By.CSS_SELECTOR, "li[aria-current='page']"), str(page+2))
            )
        else:
            break  # 没有下一页了
    except:
        break

3. 应对Zillow的反爬限制

Zillow会检测自动化操作,可能故意不加载新内容,加这些措施规避:

  • 每次操作后加随机延迟(time.sleep(random.uniform(1,3)))
  • 启动浏览器时设置随机User-Agent
  • 不要快速连续点击下一页

4. 验证页面状态

每次翻页后打印当前页码和房源数量,确认是否符合预期:

current_page = driver.find_element(By.CSS_SELECTOR, "li[aria-current='page']").text
print(f"当前页码:{current_page},房源数量:{len(listings)}")

如果页码对但房源数和第一页一样,说明等待条件不够;如果页码没变化,说明下一页按钮没点中,要检查元素定位是否正确。

针对你的代码的修改建议

假设你的main.py有翻页循环,调整成这样:

import time
import random
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from enter_data import save_data  # 你的数据保存函数

driver = webdriver.Chrome()
driver.get("https://www.zillow.com/toronto-on/rentals/")

# 先处理可能出现的弹窗
try:
    close_btn = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-testid='overlay-close']")))
    close_btn.click()
except:
    pass

max_pages = 5  # 要爬的总页数
for page in range(max_pages):
    # 等待当前页房源完全加载
    WebDriverWait(driver, 15).until(
        EC.presence_of_all_elements_located((By.CSS_SELECTOR, "div[data-testid='property-card']"))
    )
    
    # 重新获取当前页房源列表
    listings = driver.find_elements(By.CSS_SELECTOR, "div[data-testid='property-card']")
    print(f"第{page+1}页,共{len(listings)}条房源")
    
    # 提取数据
    data = []
    for listing in listings:
        try:
            price = listing.find_element(By.CSS_SELECTOR, "span[data-testid='property-card-price']").text
            address = listing.find_element(By.CSS_SELECTOR, "address[data-testid='property-card-addr']").text
            link = listing.find_element(By.CSS_SELECTOR, "a[data-testid='property-card-link']").get_attribute("href")
            data.append({"price": price, "address": address, "link": link})
        except Exception as e:
            print(f"提取房源失败:{e}")
            continue
    
    # 保存数据到文件/数据库
    save_data(data)
    
    # 处理翻页
    if page < max_pages -1:
        try:
            next_btn = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, "button[aria-label='Next page']"))
            )
            # 随机延迟避免被封
            time.sleep(random.uniform(1.5, 3))
            next_btn.click()
            
            # 等待页码更新
            WebDriverWait(driver, 10).until(
                EC.text_to_be_present_in_element((By.CSS_SELECTOR, "li[aria-current='page']"), str(page+2))
            )
        except Exception as e:
            print(f"翻页失败:{e}")
            break

driver.quit()

注意事项

  • Zillow的页面元素选择器可能会更新,定期检查调整CSS_SELECTOR
  • 如果遇到Cloudflare验证,可能需要加验证码处理或用代理IP
  • 遵守Zillow的使用条款,不要过度爬取导致账号被封

内容的提问来源于stack exchange,提问作者huhjunn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 12:48:23