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

Python Selenium无限滚动问题:爬取KW代理页面脚本卡顿求助

解决KW网站房产代理信息爬取的滚动加载问题

原脚本核心问题分析

  • 总代理数量硬编码,未从页面动态抓取,导致循环逻辑与实际页面数据不匹配
  • 滚动触发时机滞后,仅在每50条时执行一次PAGE_DOWN,无法及时触发滚动加载
  • 详情页用requests.get请求,脱离浏览器会话,可能无法获取完整数据
  • 依赖固定索引的XPath定位,页面加载后元素位置易变,导致定位失败
  • 异常处理过于宽泛,无法精准定位问题点

修改后的完整脚本

import time
from bs4 import BeautifulSoup
import json
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pandas as pd
import re

# 初始化浏览器
driver = webdriver.Chrome()
driver.get("https://www.kw.com/agent/search/ca/")
driver.maximize_window()
wait = WebDriverWait(driver, 15)

# 处理Cookie弹窗
try:
    accept_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#__next > div.app.app--consumer > div.KWBanner.KWBanner--cookieAcceptance > div > button")))
    accept_btn.click()
except Exception as e:
    print(f"Cookie按钮处理失败: {e}")

# 动态获取总代理数量
def get_total_agents():
    try:
        total_elem = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "FindAgentRoute__totalCount")))
        match = re.search(r'Showing ([0-9,]+) Agents', total_elem.text)
        if match:
            return int(match.group(1).replace(',', ''))
        return 0
    except Exception as e:
        print(f"获取总数量失败: {e}")
        return 0

total_agents = get_total_agents()
if total_agents == 0:
    print("无法获取总代理数量,退出脚本")
    driver.quit()
print(f"总代理数量: {total_agents}")

# 滚动到页面底部触发加载
def scroll_to_load():
    # 滚动到当前最后一个AgentCard元素
    try:
        last_card = driver.find_elements(By.CLASS_NAME, "AgentCard")[-1]
        ActionChains(driver).move_to_element(last_card).perform()
        time.sleep(3)
        # 额外滚动一点确保加载
        driver.execute_script("window.scrollBy(0, 300);")
        time.sleep(2)
    except IndexError:
        # 没有找到AgentCard时直接滚动到底部
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(3)

# 提取详情页数据
def extract_agent_data():
    soup = BeautifulSoup(driver.page_source, 'lxml')
    json_data = json.loads(soup.find('script', {'id': '__NEXT_DATA__'}).get_text())
    agent_data = json_data['props']['pageProps']['agentData']
    return {
        'Name': agent_data['name']['full'],
        'City': agent_data['location']['city'],
        'State': agent_data['location']['state'],
        'Email': agent_data.get('email', '无'),
        'Website': agent_data.get('website', '无')
    }

# 初始化CSV文件
pd.DataFrame(columns=['Name', 'City', 'State', 'Email', 'Website']).to_csv('kw_agents.csv', index=False)

# 爬取逻辑
processed_count = 0
try:
    while processed_count < total_agents:
        # 获取当前已加载的代理卡片
        agent_cards = wait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, "AgentCard")))
        # 处理未爬取的卡片
        for idx in range(processed_count, len(agent_cards)):
            if processed_count >= total_agents:
                break
            card = agent_cards[idx]
            try:
                # 点击卡片进入详情页
                card.click()
                wait.until(EC.presence_of_element_located((By.CLASS_NAME, "AgentContent__section")))
                # 提取数据
                agent_info = extract_agent_data()
                print(f"已爬取: {agent_info['Name']}")
                # 写入CSV
                pd.DataFrame([agent_info]).to_csv('kw_agents.csv', mode='a', header=False, index=False)
                processed_count += 1
                # 返回列表页
                driver.back()
                # 等待列表页加载完成
                wait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, "AgentCard")))
            except Exception as e:
                print(f"处理第{idx+1}个代理失败: {e}")
                driver.back()
                continue
        # 滚动加载更多
        if processed_count < total_agents:
            scroll_to_load()
except Exception as e:
    print(f"爬取过程出错: {e}")
finally:
    driver.quit()
    print(f"爬取完成,共获取{processed_count}条代理信息")

关键修改点说明

  • 动态获取总数量:从页面实际元素中提取总代理数,避免硬编码错误
  • 滚动逻辑优化:滚动到当前最后一个代理卡片,触发精准加载,同时增加等待时间确保内容加载完成
  • 详情页数据提取:直接使用driver.page_source获取页面内容,保留浏览器会话状态,确保数据正确
  • 循环逻辑调整:基于已加载的卡片数量动态处理,避免固定索引的定位问题
  • 异常处理细化:针对不同步骤捕获异常,便于排查问题,同时在出错后自动返回列表页继续爬取
  • CSV初始化优化:提前创建表头,避免重复写入

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 05:35:12