Scrapy结合Selenium实现滚动翻页数据采集

引言
在当今的互联网数据采集领域,许多网站采用动态加载技术(如AJAX、无限滚动)来优化用户体验。传统的基于Requests或Scrapy的爬虫难以直接获取动态渲染的数据,而Selenium可以模拟浏览器行为,实现滚动翻页和动态内容加载。
本文将介绍如何结合Scrapy(强大的Python爬虫框架)和Selenium(浏览器自动化工具)来高效采集滚动翻页的动态网页数据,并提供完整的代码实现。
1. 技术选型与原理
1.1 Scrapy简介
Scrapy是一个高效的Python爬虫框架,支持异步请求、数据解析和存储。它适用于静态网页抓取,但对动态渲染的页面(如JavaScript加载的内容)支持有限。
1.2 Selenium简介
Selenium是一个自动化测试工具,可以模拟用户操作(如点击、滚动、输入等),适用于动态网页的数据采集。
1.3 为什么结合Scrapy和Selenium?
- Scrapy 负责高效的数据抓取、解析和存储。
- Selenium 负责模拟浏览器行为,处理动态加载内容。
- 结合优势:Scrapy的调度能力 + Selenium的动态渲染能力,适用于复杂动态网页的采集。
二、环境搭建与工具准备
在开始实现滚动翻页数据采集之前,我们需要准备好相关的开发环境和工具。
(一)Python环境
确保你的系统中已经安装了Python,并且版本不低于3.6。Python是Scrapy和Selenium的基础运行环境,建议使用虚拟环境来管理项目依赖。
(二)Scrapy框架安装
Scrapy是一个开源的Python爬虫框架,用于快速构建高效的网页爬虫。
(三)Selenium工具安装
Selenium是一个自动化测试工具,能够模拟用户在浏览器中的行为。安装Selenium的Python绑定:
此外,还需要下载对应浏览器的驱动程序,例如ChromeDriver。根据你的浏览器版本选择合适的驱动程序,并确保其路径可以被Selenium访问。可以将其加入系统的环境变量,或者在代码中指定路径。
三、Scrapy项目创建与配置
创建一个新的Scrapy项目,用于实现滚动翻页数据采集。
(一)项目结构
Scrapy项目通常具有以下结构:
scroll_crawler/scrapy.cfgscroll_crawler/__init__.pyitems.pymiddlewares.pypipelines.pysettings.pyspiders/__init__.pyscroll_spider.py
(二)配置文件设置
在settings.py文件中,我们需要进行一些配置,以便Scrapy能够与Selenium协同工作。
- 启用Selenium中间件 在
middlewares.py文件中,定义一个Selenium中间件,用于在Scrapy请求中嵌入Selenium的浏览器操作。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from scrapy.http import HtmlResponseclass SeleniumMiddleware:def __init__(self):chrome_options = Options()chrome_options.add_argument('--headless') # 无头模式self.driver = webdriver.Chrome(options=chrome_options)def process_request(self, request, spider):self.driver.get(request.url)# 模拟滚动翻页操作self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")body = self.driver.page_sourcereturn HtmlResponse(self.driver.current_url, body=body, encoding='utf-8', request=request)
- 启用中间件 在
settings.py文件中,启用我们刚刚定义的Selenium中间件。
DOWNLOADER_MIDDLEWARES = {'scroll_crawler.middlewares.SeleniumMiddleware': 543,
}
四、实现滚动翻页数据采集
在spiders目录下创建一个爬虫文件scroll_spider.py,用于实现滚动翻页数据采集。
(一)导入依赖
import scrapy
from scrapy.exceptions import CloseSpider
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
(二)定义爬虫类
import scrapy
from scrapy.exceptions import CloseSpider
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
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.proxy import Proxy, ProxyType# 代理信息
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"class ScrollSpider(scrapy.Spider):name = 'scroll_spider'allowed_domains = ['example.com'] # 替换为目标网站域名start_urls = ['https://example.com/scroll-page'] # 替换为目标网页URLdef parse(self, response):# 使用Selenium获取动态加载的数据driver = response.meta['driver']try:# 等待页面加载完成WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.data-item')) # 替换为目标数据的选择器)except TimeoutException:raise CloseSpider('页面加载超时')# 模拟滚动翻页while True:# 获取当前页面的数据data_items = driver.find_elements(By.CSS_SELECTOR, 'div.data-item')for item in data_items:yield {'data': item.text # 替换为目标数据的提取方式}# 滚动到页面底部driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")# 等待新数据加载try:WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.data-item.new')) # 替换为新数据的选择器)except TimeoutException:# 如果没有新数据加载,退出循环break# 关闭浏览器driver.quit()# 中间件部分
class SeleniumMiddleware:def __init__(self):# 设置代理proxy = f"{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"chrome_options = Options()chrome_options.add_argument('--headless') # 无头模式chrome_options.add_argument(f"--proxy-server={proxy}")# 设置代理认证pluginfile = 'proxy_auth_plugin.zip' # 代理插件文件路径chrome_options.add_extension(pluginfile)self.driver = webdriver.Chrome(options=chrome_options)def process_request(self, request, spider):self.driver.get(request.url)# 模拟滚动翻页操作self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")body = self.driver.page_sourcereturn HtmlResponse(self.driver.current_url, body=body, encoding='utf-8', request=request)
五、代码实现细节与注意事项
(一)Selenium的无头模式
在SeleniumMiddleware中,我们使用了无头模式(--headless),这样可以避免浏览器界面的弹出,提高爬虫的运行效率。同时,无头模式也减少了对系统资源的占用。
(二)动态等待与超时处理
在爬虫代码中,我们使用了WebDriverWait来等待目标元素的加载。通过设置合理的超时时间,可以避免爬虫因页面加载过慢而卡死。如果在指定时间内目标元素未能加载完成,将抛出TimeoutException,并关闭爬虫。
(三)滚动翻页的实现
通过driver.execute_script方法,我们模拟了用户滚动页面的行为。每次滚动到页面底部后,等待新数据加载完成,然后继续滚动。当没有新数据加载时,退出循环,完成数据采集。
(四)数据提取与存储
在parse方法中,我们通过Selenium的find_elements方法获取目标数据,并将其提取为字典格式。Scrapy会自动将这些数据存储到指定的存储介质中,例如JSON文件、数据库等。
六、总结与展望
通过Scrapy与Selenium的结合,我们成功实现了滚动翻页数据采集。这种技术方案能够有效地应对动态加载的网页,获取隐藏在滚动翻页中的有价值数据。然而,需要注意的是,这种方案也存在一些局限性。例如,Selenium的运行速度相对较慢,可能会对爬虫的效率产生一定影响。此外,频繁的浏览器操作可能会对目标网站的服务器造成较大压力,因此在实际应用中需要合理控制爬虫的频率和并发数。
相关文章:
Scrapy结合Selenium实现滚动翻页数据采集
引言 在当今的互联网数据采集领域,许多网站采用动态加载技术(如AJAX、无限滚动)来优化用户体验。传统的基于Requests或Scrapy的爬虫难以直接获取动态渲染的数据,而Selenium可以模拟浏览器行为,实现滚动翻页和动态内容…...
Node.js从0.5到1学习计划
以下是针对零基础学习者的10天Node.js高效学习计划,每天聚焦核心知识点并配合实战练习: 📆 10天Node.js速成计划(每日4-6小时) 核心目标:掌握Node.js核心机制 完成3个实战项目 📍 Day 1-2&…...
python 的 obj的key 变成双引号
在Python中,当你序列化一个对象(例如使用json.dumps()方法将对象转换为JSON字符串)时,默认情况下,字典的键(keys)会被转换为字符串。如果你的字典中的键本身就是字符串,并且你想要在…...
sqlmap 源码阅读与流程分析
0x01 前言 还是代码功底太差,所以想尝试阅读 sqlmap 源码一下,并且自己用 golang 重构,到后面会进行 ysoserial 的改写;以及 xray 的重构,当然那个应该会很多参考 cel-go 项目 0x02 环境准备 sqlmap 的项目地址&…...
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例6,TableView16_06 分页表格拖拽排序
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
asp.net mvc 向前端响应json数据。用到jquery
最近在给客户开发提醒软件时,用asp.net mvc 开发。该框架已经集成了bootstrap,直接贴asp.net mvc 端代码: {Layout null; }<!DOCTYPE html><html> <head><meta name"viewport" content"widthdevice-width" /…...
基于物联网的新房甲醛浓度监测系统的设计(论文+源码)
2.1总体方案设计 本次基于物联网的新房甲醛浓度监测系统的设计其系统总体架构如图2.1所示,整个系统在硬件架构上采用了STM32f103作为主控制器,在传感器部分采用了MQ135实现甲醛浓度的检测,并且通过ESP8266 WiFi模块将当前检测的数据传输到手…...
deadsnakes
deadsnakes 是一个 第三方 PPA(Personal Package Archive),专门为 Ubuntu 系统提供较新版本的 Python,包括旧版本(如 Python 3.9)和开发中的测试版本。它的名称是一个幽默的双关,源自电影《Mont…...
Stable Diffusion 图标与像素风格LoRA训练的模型选择及参数设置
图标与像素风格LoRA训练的模型选择及参数设置指导意见 一、基础模型选型策略 图标生成推荐模型 Stable Diffusion 2.1-base 适用场景:通用UI图标、矢量风格设计核心优势:支持768x768分辨率,对几何形状捕捉精准需加载VAE模型:vae…...
【AI学习】人工神经网络
1,人工神经网络(Artificial Neural Networks,ANNs,连接模型,Connection Model) 模仿动物神经网络行为特征(突触联接的结构),进行分布式并行信息处理的算法数学模型。依靠系统的复杂程度,通过调整内部大量节点之间相互连接的关系,从而达到处理信息的目的。 2,前馈神…...
linux--网络协议初识
linux–网络协议初识 事实: 通信的主机之间距离变长了---->引发出新的通信问题? 如何使用数据问题(应用层)可靠性问题(传输层)主机定位问题(网络层)数据报局域网转发问题(数据链路层) 人提出网络协议解决方案—方案有好有坏–为了方便扩展,替换或维护–故将网络协议设置…...
Linux MariaDB部署
1:查看Linux系统版本 cat /etc/os-release#返回结果: NAME"CentOS Linux" VERSION"7 (Core)" ID"centos" ID_LIKE"rhel fedora" VERSION_ID"7" PRETTY_NAME"CentOS Linux 7 (Core)" ANSI…...
window系统下安装elk
Elasticsearch、logstash、kibana 都为8.17.3版本 Elasticsearch 安装流程 # 下载 https://www.elastic.co/cn/downloads/elasticsearch#ga-release elasticsearch-8.17.3-windows-x86_64 # 解压配置 elasticsearch.yml,下个代码块 # bin目录下双击下述文件&…...
uniapp用户登录及获取用户信息(头像昵称)
低版本情况 微信开发者工具的基础库版本要调到2.27版本以下,能够直接申请用户权限获取用户信息,但是会仅限于开发者调试,在真机测试或已上传的小程序在手机上就不能获取以上的原因是微信小程序wx.getUserProfile 和wx.getUserInfo 这两个获取…...
第五周日志-重新学汇编(2)
机器语言 汇编语言(直接在硬件上工作——硬件系统结构): 1.机器语言 每一种微处理器硬件设计和内部结构不同(决定了电信号不同,进而需要不同的机器指令) #早期通过纸带机/卡片机输入计算机,进行运算 2…...
Linux下EC11旋转编码器驱动调试
文章目录 1、前言2、使用gpio-keys驱动2.1、dts配置2.2、识别原理2.3、应用层驱动实现2.4、编译测试 3、使用rotary-encoder驱动3.1、dts配置3.2、app测试程序编写3.3、编译测试 4、总结 1、前言 本来是没有这篇文章的。最近在rk3576下调试ec11旋转编码器时,一直没…...
【无标题】Java的基础准备
一、cmd的常见命令 盘符名称冒号 说明:盘符切换dir 说明:查看当前路径下的内容cd目录 说明:进入单极目录cd.. 说明:回退到上一级目录cd目录1\目录2\... 说明:进入多级目录cd\ …...
【数学建模】(启发式算法)遗传算法:自然选择的计算模型
遗传算法:自然选择的计算模型 文章目录 遗传算法:自然选择的计算模型1. 引言2. 遗传算法的基本原理2.1 基本概念2.2 算法流程 3. 编码方式3.1 二进制编码3.2 实数编码3.3 排列编码 4. 选择操作4.1 轮盘赌选择4.2 锦标赛选择4.3 精英保留策略 5. 交叉操作…...
嵌入式八股,static在Linux驱动编写时的用处
1. 限制作用域 static关键字可以用来限制函数或变量的作用域,使其只能在当前文件内被访问。这有助于避免命名冲突,并提高代码的模块化和可维护性。 只能在当前文件里访问,或调用当前文件里有的函数。 // 文件 A.h static int globalVar 1…...
RCE——回调后门
目录 rce简述 rce漏洞 rce漏洞产生分类 rce漏洞级别 创造tips的秘籍——回调后门 call_user_func 解析 如何执行后门 call_user_func_array array_filter、array_map 解析 如何执行后门 php5.4.8中的assert——二参数的回调函数 uasort uksort array_reduce() …...
JavaScript 调试入门指南
JavaScript 调试入门指南 一、调试准备阶段 1. 必备工具配置 浏览器套件:安装最新Chrome102+,开启实验性功能(地址栏输入chrome://flags/#enable-devtools-experiments)编辑器集成:VS Code安装以下扩展: JavaScript Debugger:支持浏览器与Node.js双端调试Error Lens:实…...
字节真题,问a,b,c指的地址是否相同?
题目: class A{ int a, int d } class B { int b }class C: public A,public B { int b } C* c new C; A* a c; B* b c; 问a,b,c指的地址是否相同? 在 C 中,由于类的继承关系以及内存布局的规则,a、b 和 c 指针的地址可能不…...
2025年03月18日柯莱特(外包宁德)一面前端面试
目录 自我介绍你怎么从0到1搭建项目的webpack 的构建流程手写webpack插件你有什么想问我的吗 2. 你怎么从 0 到 1 搭建项目的 在面试中回答从 0 到 1 搭建前端项目,可按以下详细步骤阐述: 1. 项目前期准备 需求理解与分析 和产品经理、客户等相关人…...
OpenGL ES 2.0与OpenGL ES 3.1的区别
如果硬件支持且需要更高质量的图形效果,推荐3.1;如果兼容性和开发简便更重要,且效果需求不高,2.0更合适。不过现代车载系统可能越来越多支持3.x版本,所以可能倾向于使用3.1,但具体情况还需调查目标平台的硬…...
Unity Shader 学习17:合批渲染
一、基础概念 合批主要是针对这三个概念进行优化减少: ① SetPass Call:一次渲染状态切换,也就是每次切换 材质/Pass 时,就会触发一次SetPass Call ② Draw Call:cpu 调用一次 gpu 绘制函数 ③ Batch:表示…...
带你从入门到精通——自然语言处理(十. BERT)
建议先阅读我之前的博客,掌握一定的自然语言处理前置知识后再阅读本文,链接如下: 带你从入门到精通——自然语言处理(一. 文本的基本预处理方法和张量表示)-CSDN博客 带你从入门到精通——自然语言处理(二…...
vue3 数据监听(watch、watchEffect)
1、watch 1.1基本使用 作用:数据监听 语法: watch(监听的数据, (改变后的数据, 改变前的数据) > { console.log(newVal, oldVal); }) 注意点:watch写法上支持一个或者多个监听源,这些监听源必须只能是getter/effect函数…...
Vue 3中的Teleport:超越组件边界的渲染
Vue 3引入了许多新特性,其中之一便是Teleport。它为开发者提供了一种强有力的方式来控制组件的渲染位置,使得我们可以将组件的内容“传送”到DOM树的任何地方,而不仅仅局限于其父级组件的边界内。这在创建模态框、通知系统或任何需要脱离当前…...
【计算机网络】DHCP工作原理
DHCP(动态主机配置协议) Dynamic Host Configuration Protocol 基于UDP协议传输 DHCP分配IP地址的过程 (1)DHCP DISCOVER客户机请求 IP 地址: 当一个 DHCP 客户机启动时,客户机还没有 IP 地址,所以客户机要通过 DHC…...
Linux网站搭建(新手必看)
1.宝塔Linux面板的功能 宝塔面板是一款服务器管理软件,可以帮助用户建立网站,一键配置服务器环境,使得用户通过web界面就可以轻松的管理安装所用的服务器软件。 2. 宝塔Linux面板的安装 宝塔官网地址:宝塔面板 - 简单好用的Linu…...
