Scrapy-Selenium无法抓取商品详情、尺码模块数据如何解决
问题根因
你的代码存在5个直接导致抓取失败的错误:
- 缩进语法错误:
start_requests、parse两个方法没有缩进至ProductsSpider类内部,属于全局函数,Scrapy运行时根本不会调用你写的这部分逻辑,实际执行的是Spider父类的默认方法。 - 浏览器实例冲突:你在
start_requests里手动初始化了独立的Chrome driver,和scrapy-selenium中间件维护的driver是完全隔离的两个实例。你在自己开的driver里做的等待加载、关闭cookie横幅操作,scrapy-selenium发请求用的driver完全感知不到,相当于白做。 - 等待时长不足:你给详情页SeleniumRequest设置的
wait_time=1过短,商品详情表格、尺码选择模块都是延迟加载的动态内容,1秒时间不足以完成渲染。 - 请求逻辑混乱:你在手动初始化的driver逻辑最后调用了
return super().start_requests(),这个方法会默认请求未定义的start_urls,和前面yield的详情页请求混在一起,执行流程完全错乱。 - 选择器缺失+反爬识别:你在parse方法里写的XPath只覆盖了标题、价格、商品描述三个字段,根本没有编写对应商品详情表格、尺码选择模块的提取规则;另外scrapy-selenium默认的浏览器参数没有做反爬规避,很容易被站点识别为爬虫,返回不完整的渲染结果。
修正方案
- 所有类方法保持正确缩进,删掉手动初始化driver、手动调用
super().start_requests()的冗余逻辑,所有浏览器操作统一通过scrapy-selenium维护的driver实例处理,不要同时开两套浏览器。 - 统一配置Chrome启动参数:设置固定窗口大小、启用新版无头模式、禁用自动化检测特征,避免被站点反爬识别。
- 替换固定时长的
time.sleep()为显式等待,等目标元素加载完成后再做操作,既保证渲染完成,又不浪费无意义的等待时间。 - 补充商品详情表格、尺码选择模块对应的XPath提取规则,等尺码模块加载完成后再提取页面内容。
修正后可运行代码
import scrapy from scrapy_selenium import SeleniumRequest from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager class ProductsSpider(scrapy.Spider): name = 'products' allowed_domains = ['www.breuninger.com'] custom_settings = { 'SELENIUM_DRIVER_NAME': 'chrome', 'SELENIUM_DRIVER_EXECUTABLE_PATH': ChromeDriverManager().install(), 'SELENIUM_DRIVER_ARGUMENTS': [ '--headless=new', '--window-size=1920,1080', '--disable-blink-features=AutomationControlled', '--no-sandbox', '--disable-dev-shm-usage' ], 'DOWNLOADER_MIDDLEWARES': { 'scrapy_selenium.SeleniumMiddleware': 800 } } def start_requests(self): list_url = "https://www.breuninger.com/de/damen/luxus/bekleidung-jacken-maentel/" yield SeleniumRequest( url=list_url, callback=self.parse_list, wait_time=10, wait_until=EC.presence_of_element_located((By.XPATH, "//suchen-produktliste[@id='produktliste']//suchen-produkt//a")) ) def parse_list(self, response): driver = response.request.meta['driver'] wait = WebDriverWait(driver, 10) # 关闭cookie同意横幅 try: banner_btn = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[@class='banner-actions-container']/button"))) banner_btn.click() except: pass # 滚动页面触发商品列表懒加载 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") wait.until(EC.presence_of_all_elements_located((By.XPATH, "//suchen-produktliste[@id='produktliste']/section/div/suchen-produkt/div/a"))) product_links = response.xpath("//suchen-produktliste[@id='produktliste']/section/div/suchen-produkt/div/a/@href").getall() for href in product_links: yield SeleniumRequest( url=response.urljoin(href), callback=self.parse_detail, wait_time=15, # 显式等待尺码模块加载完成,确保动态区块渲染完毕 wait_until=EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'size-selector')]//button")) ) def parse_detail(self, response): item = { 'Bold-title': response.xpath("(//span[@itemprop='name'])[1]/text()").get(), 'Price': response.xpath("//div[@itemprop='offers']/span/text()").get(), 'Beschreibung': response.xpath("//div[@class='bewerten-textformat--produktdetails-detail']/div/ul/li/text()").getall() } # 提取表格形式的商品详情 detail_table = {} table_rows = response.xpath("//div[contains(@class, 'product-attributes')]//tr") for row in table_rows: key = row.xpath("./th/text()").get(default='').strip() value = row.xpath("./td//text()").get(default='').strip() if key and value: detail_table[key] = value item['product_detail_table'] = detail_table # 提取尺码选择模块数据 size_list = [] size_buttons = response.xpath("//div[contains(@class, 'size-selector')]//button") for btn in size_buttons: size_val = btn.xpath(".//span[contains(@class, 'size-label')]/text()").get(default='').strip() is_available = 'disabled' not in btn.xpath("./@class").get(default='') size_list.append({ 'size': size_val, 'in_stock': is_available }) item['size_selector'] = size_list yield item
额外说明
- 不要混用手动初始化的Selenium driver和scrapy-selenium的内置driver,两套实例的cookie、页面状态完全不互通,是你之前抓取失败的核心原因。
- Chrome浏览器请使用
--headless=new新版无头模式,旧版无头模式极易被电商站点反爬识别,返回不完整内容。 - 如果页面还有未加载的动态内容,可以在解析前加一段滚动逻辑,触发懒加载元素渲染。
内容的提问来源于stack exchange,提问作者Raisul Islam
相关产品推荐
相关产品推荐

