使用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
相关产品推荐
相关产品推荐

