如何提升基于Selenium的Target网站数据爬取速度?
Target爬虫效率优化方案
核心问题分析
你的脚本爬取速度慢的核心原因是大量固定时长的time.sleep()——不管目标元素是否加载完成,都强制等待固定时间,浪费了大量不必要的等待时长。此外,元素定位器过度依赖页面绝对结构,不仅容易失效,定位效率也偏低,滚动加载的逻辑也不够灵活。
具体优化措施
1. 用显式等待替代所有time.sleep()
显式等待会在元素满足指定条件(比如可点击、可见)时立即执行操作,无需固定等待,这是提升爬取效率的关键。需要先导入对应模块:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC
2. 优化元素定位器
抛弃冗长的绝对XPATH,改用更稳定的相对定位器(比如CSS选择器、基于文本/属性的XPATH),既减少页面结构变化带来的定位失败风险,也能提升元素定位速度。
3. 简化滚动加载逻辑
无需分段固定滚动+等待,直接滚动到页面底部触发内容加载,配合显式等待判断新内容是否加载完成,避免无意义的等待。
4. 优化Load More按钮的定位逻辑
直接定位包含"Load"文本的按钮,无需遍历所有匹配元素,减少不必要的操作步骤。
修改后的示例代码
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC options = Options() options.add_argument('--headless=new') # 启用eager加载策略,DOM加载完成后即可操作,无需等待所有资源加载 options.page_load_strategy = 'eager' driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options) # 设置显式等待超时时间(可根据网络情况调整,比如10秒) wait = WebDriverWait(driver, 10) lstReview = [] name = 'Target' x_lst = [] for dpci in files: print(dpci) lstTitles = [] OverallRating = "" # 导航到搜索页面 driver.get(f'https://www.target.com/s?searchTerm={dpci}') # 等待搜索结果链接出现,获取第一个产品链接 try: first_product_link = wait.until( EC.presence_of_element_located( (By.CSS_SELECTOR, '[data-test="product-title"] a') ) ) first_product_link.click() except: print(f"No product found for DPCI: {dpci}") continue # 滚动到页面底部触发内容加载 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 循环点击Load More按钮直到按钮消失 while True: try: # 等待Load More按钮可点击,且文本包含Load load_more_btn = wait.until( EC.element_to_be_clickable( (By.XPATH, '//button[contains(text(), "Load")]') ) ) load_more_btn.click() # 等待按钮失效,说明新内容正在加载 wait.until(EC.staleness_of(load_more_btn)) except: # 没有Load More按钮时退出循环 break # 等待所有评论标题加载完成 review_titles = wait.until( EC.presence_of_all_elements_located( (By.CLASS_NAME, 'jfrTHg') ) ) # 提取评论标题 for title in review_titles: lstTitles.append(title.get_attribute('innerText')) print("Moving to next DPCI") driver.quit()
额外优化建议
- 禁止混用隐式等待和显式等待:官方文档明确不建议同时使用两种等待方式,会导致等待时长不可控,优先使用显式等待即可。
- 多线程/多进程并行处理:如果需要处理大量DPCI,可以用
concurrent.futures开启多线程(注意控制请求频率,避免触发Target反爬机制)。 - 反爬应对:设置真实的User-Agent,必要时加入随机范围的延迟(用
random.uniform(min, max)替代固定等待),降低被封禁的风险。
内容的提问来源于stack exchange,提问作者Faraz Khan
相关产品推荐
相关产品推荐

