Scrapy结合Selenium爬取动态加载内容及Excel URL入库技术问询
我明白你现在的困境——动态加载内容确实是爬虫的常见痛点,尤其是Scrapy默认没法处理JS渲染的内容,Splash有时候也会因为页面渲染机制的问题失效。咱们先从Selenium的正确实现开始,然后再聊聊其他可行的方案。
一、Selenium 获取动态文本的可行示例
首先要纠正你当前代码里的小问题:你同时初始化了独立的driver实例和使用SeleniumRequest,这会导致资源冲突。下面分两种场景给出可行代码:
1. 纯Selenium独立爬取示例(适合调试验证)
这个示例优先直接获取页面渲染后的文本,比截图OCR高效得多,还能处理懒加载内容:
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 from selenium.common.exceptions import TimeoutException, NoSuchElementException import time from webdriver_manager.chrome import ChromeDriverManager def scrape_dynamic_content(url): # 自动管理ChromeDriver,无需手动配置路径 driver = webdriver.Chrome(ChromeDriverManager().install()) try: driver.get(url) # 等待页面核心动态元素加载完成(替换成目标页面的实际元素选择器) wait = WebDriverWait(driver, 15) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".product-listing"))) # 滚动页面处理懒加载,确保所有内容加载完毕 last_height = driver.execute_script("return document.body.scrollHeight") while True: driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(2) new_height = driver.execute_script("return document.body.scrollHeight") if new_height == last_height: break last_height = new_height # 获取页面文本(可选择整页或指定元素) # 方式1:获取整个页面文本 page_text = driver.find_element(By.TAG_NAME, "body").text # 方式2:获取指定区块文本(更精准) # page_text = driver.find_element(By.CSS_SELECTOR, ".product-listing").text return page_text except TimeoutException: print(f"页面加载超时:{url}") except NoSuchElementException: print(f"未找到目标元素:{url}") finally: driver.quit() # 测试调用 scrape_dynamic_content("https://www.analog.com/en/products/landing-pages/new-products-listing.html")
2. Scrapy集成Selenium的正确写法
如果要在Scrapy框架里使用,建议依托scrapy-selenium的内置Driver管理,不要自己初始化Driver:
import scrapy from scrapy_selenium import SeleniumRequest from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC class QuotesSpider(scrapy.Spider): name = "quotes" def start_requests(self): urls = [ 'https://www.analog.com/en/products/landing-pages/new-products-listing.html', ] for url in urls: yield SeleniumRequest( url=url, callback=self.parse, wait_time=15, # 等待目标元素加载完成后再回调 wait_until=EC.presence_of_element_located((By.CSS_SELECTOR, ".product-listing")), # 滚动页面触发懒加载 script='window.scrollTo(0, document.body.scrollHeight);' ) def parse(self, response): # 从response元数据中获取Selenium Driver实例 driver = response.meta['driver'] # 获取页面文本 page_text = driver.find_element(By.TAG_NAME, "body").text # 后续可将page_text写入数据库,这里先返回示例数据 yield { 'url': response.url, 'content': page_text[:500] # 只返回前500字符示例 }
二、其他可行方案
如果Selenium还是不顺畅,试试这些替代思路:
方案1:直接爬取后端API接口
很多动态内容是通过XHR/Fetch请求从后端API获取的。打开浏览器开发者工具(F12),切换到Network标签筛选XHR请求,找到返回目标内容的API接口,直接用Scrapy请求这些接口——这种方式比渲染整个页面高效10倍以上,还能拿到结构化的JSON数据。方案2:用Playwright替代Selenium
Playwright是微软推出的自动化工具,对现代前端框架(React/Vue)的支持更好,内置智能等待机制,代码更简洁:
from playwright.sync_api import sync_playwright def scrape_with_playwright(url): with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto(url) # 等待页面网络空闲(所有请求完成) page.wait_for_load_state("networkidle") # 滚动页面触发懒加载 page.evaluate("window.scrollTo(0, document.body.scrollHeight)") page.wait_for_timeout(2000) # 获取文本内容 page_text = page.locator("body").text_content() browser.close() return page_text
- 方案3:万不得已时用OCR提取文本
如果页面内容确实是图片形式(比如图片化的产品说明),再考虑OCR。需要安装pytesseract和Pillow:
from selenium import webdriver from PIL import Image import pytesseract # Windows系统需指定Tesseract路径,Mac/Linux可忽略 # pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' def scrape_with_ocr(url): driver = webdriver.Chrome() driver.get(url) # 截取整页截图 driver.save_screenshot("page_screenshot.png") # 识别图片文本 img = Image.open("page_screenshot.png") text = pytesseract.image_to_string(img) driver.quit() return text
注意:OCR准确率受图片清晰度、字体影响较大,不到万不得已不推荐使用。
内容的提问来源于stack exchange,提问作者Amarjot Singh




