Python3 Selenium点击元素失败处理及多URL爬取、BS4替代方案咨询
解决方案
1 解决点击被cookie横幅拦截的报错
报错的核心原因是页面底部的cookie提示框遮挡了目标按钮的位置,selenium默认的模拟点击要求元素完全可见且不被遮挡,两种修复方案可选:
方案A:先关闭cookie横幅
进入页面后先定位cookie的同意按钮点击移除横幅,再操作目标元素,示例代码:
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 chrome_path = r"C:\Users\lenovo\Downloads\chromedriver_win32 (5)\chromedriver.exe" driver = webdriver.Chrome(chrome_path) driver.get("https://www.autotrader.ca/a/ram/1500/hamilton/ontario/19_12052335_/?showcpo=ShowCpo&ncse=no&ursrc=pl&urp=2&urm=8&sprx=-2") # 等待cookie横幅加载完成,点击同意按钮(根据实际页面的按钮选择器调整) wait = WebDriverWait(driver, 10) cookie_agree_btn = wait.until(EC.element_to_be_clickable((By.ID, "你页面上cookie同意按钮的ID"))) cookie_agree_btn.click() # 再点击目标按钮 show_phone_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//a[@class="link ng-star-inserted"]'))) show_phone_btn.click()
方案B:用JS执行点击绕过遮挡限制
如果不想处理cookie,可以直接通过JS触发点击事件,不需要元素可见,不会被遮挡影响:
# 定位到目标按钮后直接执行JS点击 show_phone_btn = wait.until(EC.presence_of_element_located((By.XPATH, '//a[@class="link ng-star-inserted"]'))) driver.execute_script("arguments[0].click();", show_phone_btn)
2 批量处理100条以上URL的实现
按以下逻辑实现即可:
- 先把所有待爬取的URL存入列表,或存到TXT文件逐行读取
- 增加异常捕获逻辑,单条URL爬取失败时跳过并记录,不中断整体任务
- 每爬完3-5条加1-3秒随机延迟,降低被反爬拦截的概率
- 数据每爬完10条就写入一次本地CSV/JSON文件,避免程序闪退丢失数据
示例代码结构:
import time import random import csv # 读取URL列表,示例是直接写列表,也可以从txt读 url_list = [ "https://www.autotrader.ca/a/xxx", # 剩下的99+条URL ] # 结果存储文件 f = open("result.csv", "a+", encoding="utf-8", newline="") writer = csv.writer(f) writer.writerow(["车辆名称", "手机号"]) for url in url_list: try: driver.get(url) # 等待页面加载 time.sleep(random.uniform(1,2)) # 提取车辆名称 car_title = wait.until(EC.presence_of_element_located((By.XPATH, '//p[@class="hero-title"]'))).text # 点击显示手机号 show_phone_btn = wait.until(EC.presence_of_element_located((By.XPATH, '//a[@class="link ng-star-inserted"]'))) driver.execute_script("arguments[0].click();", show_phone_btn) # 等待手机号加载后提取 phone = wait.until(EC.presence_of_element_located((By.XPATH, "你提取手机号的选择器"))).text # 写入结果 writer.writerow([car_title, phone]) print(f"{url} 爬取完成") time.sleep(random.uniform(1,3)) except Exception as e: print(f"{url} 爬取失败,错误:{e}") continue f.close() driver.quit()
3 能否用BeautifulSoup提升爬取速度
单独使用BeautifulSoup无法实现该需求:手机号需要点击按钮后才会加载,属于动态生成内容,BeautifulSoup只能解析页面初始加载的静态HTML源码,初始源码中没有手机号数据,无法直接提取。
如果要提升速度,可以抓点击「Click to Show」按钮时触发的后端接口,直接用requests模拟请求接口获取手机号,不需要启动浏览器,速度是Selenium的10倍以上,拿到接口返回的JSON数据后可以直接解析,不需要用BS4也能快速提取字段。如果接口有加密、签名等复杂反爬规则,再考虑用Selenium实现。
内容的提问来源于stack exchange,提问作者Alian Nadeem
相关产品推荐
相关产品推荐

