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

Scrapy结合Selenium点击元素报Selector无法JSON序列化错误如何解决

错误原因

你的报错本质是类型不匹配:

  • 你通过response_obj.xpath拿到的link是Scrapy框架的Selector对象,仅用于内容解析,不是Selenium可以识别的浏览器原生WebElement对象
  • 调用driver.execute_script执行点击时,Selenium会尝试把传入的参数转成浏览器可识别的格式,Selector对象无法完成序列化,就会抛出这个错误

另外你现存的代码还有两处逻辑错误:

  1. 你的xpath选择的是id为tableRepeat2的tbody元素本身,不是tbody下可点击的行元素,就算类型对了也没法批量点击
  2. 提取Ocupatia字段时直接返回了Selector对象,没有调用提取方法,就算点击成功保存数据时也会报错
修复方案

核心修改逻辑是:要点击的元素直接用Selenium的API从浏览器实例中获取,不要用Scrapy的Selector获取;提取内容时加等待逻辑,提取完成后调用方法拿到实际字符串。
修复后的完整代码如下:

# -*- coding: utf-8 -*-
import scrapy

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from scrapy.selector import Selector
from scrapy_selenium import SeleniumRequest

class AnofmSpider(scrapy.Spider):
    name = 'anofm'
    
    def start_requests(self):
        yield SeleniumRequest(
            url='https://www.anofm.ro/lmvw.html?agentie=Covasna&categ=3&subcateg=1',
            callback=self.parse
        )

    def parse(self, response):  
        driver = response.meta['driver'] 
        # 等待列表加载完成
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "tableRepeat2"))
        )
        # 直接用Selenium获取所有可点击的行元素,xpath可根据实际页面可点击元素调整
        clickable_rows = driver.find_elements(By.XPATH, "//tbody[@id='tableRepeat2']/tr")
        
        for idx in range(len(clickable_rows)):
            # 每次循环重新获取元素,避免点击后后退导致元素失效
            current_row = driver.find_elements(By.XPATH, "//tbody[@id='tableRepeat2']/tr")[idx]
            # 执行点击
            driver.execute_script("arguments[0].click();", current_row)
            
            # 等待详情内容加载完成
            WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.ID, "print"))
            )
            
            # 提取内容,调用.get()拿到实际字符串
            yield {
                'Ocupatia': Selector(text=driver.page_source).xpath("//div[@id='print']/p/text()[1]").get()
            }
            
            # 点击后返回列表页,准备点下一个元素,可根据实际页面调整后退逻辑
            driver.back()
            # 等待列表重新加载
            WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.ID, "tableRepeat2"))
            )

内容的提问来源于stack exchange,提问作者Jonathan Simpson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 03:12:01