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

引言

在当今的互联网数据采集领域,许多网站采用动态加载技术(如AJAX、无限滚动)来优化用户体验。传统的基于RequestsScrapy的爬虫难以直接获取动态渲染的数据,而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项目通常具有以下结构:

plain 复制代码
scroll_crawler/
    scrapy.cfg
    scroll_crawler/
        __init__.py
        items.py
        middlewares.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            scroll_spider.py

(二)配置文件设置

settings.py文件中,我们需要进行一些配置,以便Scrapy能够与Selenium协同工作。

  1. 启用Selenium中间件 在middlewares.py文件中,定义一个Selenium中间件,用于在Scrapy请求中嵌入Selenium的浏览器操作。
python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from scrapy.http import HtmlResponse

class 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_source
        return HtmlResponse(self.driver.current_url, body=body, encoding='utf-8', request=request)
  1. 启用中间件 在settings.py文件中,启用我们刚刚定义的Selenium中间件。
python 复制代码
DOWNLOADER_MIDDLEWARES = {
    'scroll_crawler.middlewares.SeleniumMiddleware': 543,
}

四、实现滚动翻页数据采集

spiders目录下创建一个爬虫文件scroll_spider.py,用于实现滚动翻页数据采集。

(一)导入依赖

python 复制代码
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

(二)定义爬虫类

python 复制代码
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']  # 替换为目标网页URL

    def 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_source
        return 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的运行速度相对较慢,可能会对爬虫的效率产生一定影响。此外,频繁的浏览器操作可能会对目标网站的服务器造成较大压力,因此在实际应用中需要合理控制爬虫的频率和并发数。

相关推荐
API小爬虫1 小时前
如何设置动态代理提高Python爬虫稳定性?
开发语言·爬虫·python
篝火悟者1 小时前
自学-python-爬虫入门
开发语言·爬虫·python
用户929482836332 小时前
如何使用 yt-dlp 快速开发一套下载多个平台的高清视频的工具?
爬虫
ONE_Gua2 小时前
魔改chromium——源码拉取及编译
前端·后端·爬虫
春风又。3 小时前
接口自动化——初识pytest
python·测试工具·自动化·pytest
Jason-河山4 小时前
如何使用Python爬虫获取1688商品评论?
开发语言·爬虫·python
一个幽默的程序员6 小时前
如何快速备份你的 API 吗? Postman 批量导出接口
测试工具·postman
Cc_Davis_cC6 小时前
postman发送请求报文到后台中文乱码
测试工具·postman
一个幽默的程序员6 小时前
Postman 集合如何快速分享给团队?
测试工具·postman
南部余额7 小时前
playwright解决重复登录问题,通过pytest夹具自动读取storage_state用户状态信息
前端·爬虫·python·ui·pytest·pylawright