Scrapy集成Selenium时_init_方法未执行报错如何解决
问题根因
你遇到的问题来自几个明确的代码错误,按影响优先级排序:
- 最核心的错误是Python构造方法名写错了。Python类的构造方法固定为
__init__,方法名前后各需要两个下划线,你写的_init_前后只有一个下划线,本质是个完全不会被自动调用的普通方法。Scrapy实例化爬虫类时只会调用官方定义的构造方法,你写在_init_里的Selenium初始化、页面渲染代码从头到尾没执行,self.html属性根本没被赋值,自然会抛出属性不存在的错误,你加的两条print语句也当然不会输出。 - 就算改对构造方法名,你现在的写法也会出问题:重写Scrapy Spider子类的构造方法时,必须先调用父类的构造方法,否则Scrapy内置的初始化逻辑(比如配置加载、信号注册、start_urls初始化)会全部失效。
- 你代码里的部分Selenium API已经在高版本中移除:
set_window实际应为set_window_size,find_elements_by_class_name这种旧版定位方法已经被废弃,运行时会直接抛方法不存在的异常。 - 逻辑层面的小问题:你把Selenium渲染逻辑全写在构造方法里,Scrapy自带的下载器还是会按
start_urls发送一次普通HTTP请求,属于无效重复请求;如果后续要爬取多个JS渲染页面,构造方法只会在爬虫启动时执行一次,逻辑完全无法复用。
修复方案
- 把构造方法名从
_init_修正为__init__,添加可变参数*args, **kwargs,方法第一行调用父类构造方法super().__init__(*args, **kwargs),保证Scrapy自身的初始化逻辑正常执行。 - 修正Selenium的废弃API调用,补充必要的页面加载等待,避免元素未加载就点击引发的异常。
- 如果只是做简单单页测试,改完上面两点就能正常运行;如果要做批量爬取,建议把Selenium渲染逻辑抽到下载器中间件中,对接Scrapy原生的调度、重试、并发体系,不要硬塞在构造方法里。
修复后可运行代码
import scrapy from scrapy.selector import Selector from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By import time class test_2(scrapy.Spider): name = 'test_2' start_urls = [ 'https://www.jackjones.in/st-search?q=shoes' ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) print("test-1") chrome_options = Options() # 新版Chrome推荐用--headless=new参数启动无头模式 chrome_options.add_argument("--headless=new") # 如果已经把chromedriver配置到系统环境变量,不需要硬写路径 driver = webdriver.Chrome(options=chrome_options) # 修正窗口大小设置方法 driver.set_window_size(1920, 1080) driver.get("https://www.jackjones.in/st-search?q=shoes") # 等待列表页商品项加载完成,固定等待仅做演示,生产环境建议用显式等待 time.sleep(3) # 替换为新版Selenium的元素定位写法 tab = driver.find_elements(By.CLASS_NAME, "st-single-product") tab[4].click() # 等待点击后的商品详情页渲染完成 time.sleep(2) self.html = driver.page_source print("test-2") driver.quit() def parse(self, response): print("test-3") resp = Selector(text=self.html) yield { 'title': resp.xpath("//h1/text()").get() }
补充说明:代码里的
time.sleep()是最简单的等待实现,稳定性差且效率低,正式使用建议替换为Selenium的WebDriverWait显式等待,按元素加载状态判断等待时机。
内容的提问来源于stack exchange,提问作者vasu gupta
相关产品推荐
相关产品推荐

