当前位置:首页 > 技术 > 正文内容

基于 Selenium 的自动化爬虫实战与 Scrapy 框架集成指南

访客 技术 2026年5月24日 3

1. Selenium 框架概述

Selenium 是一个强大的 Web 自动化测试工具,支持多种浏览器操作。在爬虫领域,它主要用于解决动态渲染、JavaScript 加密以及复杂的交互验证等难题。Selenium 必须配合对应的浏览器驱动(Driver)才能正常工作。

1.1 环境配置

首先需要安装 Python 客户端库:

pip install selenium

1.2 驱动安装与对比

  • ChromeDriver:目前最主流的选择,性能稳定,支持 Headless(无头)模式,适用于开发调试和生产环境。
  • PhantomJS:曾经流行的无界面浏览器,但在内存占用和稳定性上表现欠佳,且目前已停止维护,建议优先使用 Chrome Headless。

安装驱动时,需确保 ChromeDriver 版本与本地 Chrome 浏览器版本一致,并将其可执行文件路径加入系统环境变量或放置在 Python 脚本同级目录下。

2. 浏览器自动化核心操作

2.1 基础交互实例

以下代码展示了如何启动浏览器、搜索关键词并进行截图存证:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time

# 配置无头模式
chrome_conf = Options()
chrome_conf.add_argument('--headless')
chrome_conf.add_argument('--disable-gpu')

# 初始化驱动
app_driver = webdriver.Chrome(options=chrome_conf)

try:
    app_driver.get('https://www.baidu.com')
    
    # 查找搜索框并输入
    search_input = app_driver.find_element_by_id('kw')
    search_input.send_keys('Python 自动化')
    
    # 模拟点击搜索按钮
    submit_btn = app_driver.find_element_by_id('su')
    submit_btn.click()
    
    time.sleep(2)
    app_driver.save_screenshot('result_page.png')
    print("当前页面源码长度:", len(app_driver.page_source))
finally:
    app_driver.quit()

2.2 处理 Iframe 嵌套

当目标元素位于 iframeframe 标签内时,需要先切换上下文:

# 找到 iframe 节点
target_frame = web_driver.find_element_by_id('login_frame')
# 切换至该框架
web_driver.switch_to.frame(target_frame)
# 操作框架内元素
user_field = web_driver.find_element_by_name('u')
user_field.send_keys('test_user')
# 切换回主文档
web_driver.switch_to.default_content()

3. 元素定位与常用属性

Selenium 提供了多种定位策略,推荐优先使用 XPath,因为它能处理复杂的层级关系:

  • find_element_by_xpath(): 定位单个元素。
  • find_elements_by_xpath(): 获取符合条件的元素列表。

获取节点信息:

element = driver.find_element_by_xpath('//div[@class="content"]')
print(element.text)  # 获取内部文本
print(element.get_attribute('href'))  # 获取指定属性
print(element.get_attribute('innerHTML'))  # 获取节点 HTML

4. 实战案例:动态加载页面爬取

4.1 京东商品信息采集

电商网站通常通过滚动加载数据,需要利用 JavaScript 模拟滚动:

class JDScraper:
    def __init__(self):
        self.worker = webdriver.Chrome()

    def fetch_data(self, keyword):
        self.worker.get('https://www.jd.com/')
        self.worker.find_element_by_id('key').send_keys(keyword)
        self.worker.find_element_by_class_name('button').click()
        time.sleep(3)
        
        # 模拟下拉滚动以触发 Ajax 加载
        self.worker.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(2)
        
        items = self.worker.find_elements_by_css_selector('.gl-item')
        for item in items:
            title = item.find_element_by_css_selector('.p-name em').text
            price = item.find_element_by_css_selector('.p-price i').text
            print(f"商品: {title[:20]}... | 价格: {price}")

    def close(self):
        self.worker.quit()

4.2 多线程加速接口爬取

对于分页式的 API 接口,结合 threadingQueue 可以显著提升效率:

import requests
from queue import Queue
from threading import Thread

class ApiTask(Thread):
    def __init__(self, task_queue):
        super().__init__()
        self.tasks = task_queue

    def run(self):
        while not self.tasks.empty():
            api_url = self.tasks.get()
            resp = requests.get(api_url, headers={'User-Agent': 'Mozilla/5.0'})
            if resp.status_code == 200:
                self.process_json(resp.json())
            self.tasks.task_done()

    def process_json(self, data):
        # 处理业务逻辑
        pass

5. 将 Selenium 集成至 Scrapy 框架

在 Scrapy 中集成 Selenium,主要是通过自定义下载中间件(Downloader Middleware)拦截请求,并使用浏览器渲染后返回 HtmlResponse

5.1 中间件实现

from scrapy.http import HtmlResponse

class SeleniumMiddleware:
    def process_request(self, request, spider):
        # 仅对特定爬虫生效
        if spider.name == "dynamic_spider":
            spider.browser.get(request.url)
            time.sleep(2)
            content = spider.browser.page_source
            return HtmlResponse(
                url=spider.browser.current_url,
                body=content,
                encoding="utf-8",
                request=request
            )
        return None

5.2 爬虫类生命周期管理

为了避免频繁开启和关闭浏览器实例,建议在爬虫初始化时创建浏览器,并在爬虫关闭时通过信号量释放资源:

import scrapy
from selenium import webdriver
from scrapy import signals

class DynamicSpider(scrapy.Spider):
    name = "dynamic_spider"

    def __init__(self, *args, **kwargs):
        super(DynamicSpider, self).__init__(*args, **kwargs)
        self.browser = webdriver.Chrome()

    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super(DynamicSpider, cls).from_crawler(crawler, *args, **kwargs)
        crawler.signals.connect(spider.finalize_browser, signal=signals.spider_closed)
        return spider

    def finalize_browser(self):
        self.browser.quit()

    def parse(self, response):
        # 解析逻辑
        pass

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。