【python】用 Scrapy 实现高效爬虫项目

news2024/11/19 2:32:23

用 Scrapy 实现高效爬虫项目

Scrapy 是一个功能强大的 Python 爬虫框架,以其高效、灵活、可扩展性而闻名。无论是处理简单的爬取任务,还是构建复杂的分布式爬虫项目,Scrapy 都能提供强有力的支持。本文将从 Scrapy 的核心概念、项目结构、优化技巧等方面,带你掌握用 Scrapy 构建高效爬虫的技巧。


一、Scrapy 的核心概念

要理解 Scrapy,首先需要掌握以下几个核心概念:

  • Spider: 爬虫类,定义爬取逻辑和处理逻辑。
  • Request: 发起 HTTP 请求,支持各种参数(如 headers、cookies 等)。
  • Response: 请求的结果,包含网页内容及相关信息。
  • Item: 数据结构,用于存储爬取到的内容。
  • Pipeline: 数据处理管道,用于清洗、存储数据。
  • Middleware: 中间件,用于处理请求和响应的行为。

二、快速搭建 Scrapy 项目

1. 创建项目

使用 scrapy startproject 命令快速生成项目模板:

scrapy startproject myproject

生成的项目结构如下:

myproject/
    scrapy.cfg           # 项目配置文件
    myproject/
        __init__.py
        items.py        # 定义数据结构
        middlewares.py  # 定义中间件
        pipelines.py    # 定义数据管道
        settings.py     # 项目设置
        spiders/        # 存放爬虫文件

2. 编写 Spider

Spider 是 Scrapy 的核心,用于定义爬取的逻辑。

创建一个简单的爬虫:

scrapy genspider example example.com

编辑 example.py

import scrapy

class ExampleSpider(scrapy.Spider):
    name = "example"
    start_urls = ['http://example.com']

    def parse(self, response):
        for title in response.css('h1::text').getall():
            yield {'title': title}

运行爬虫:

scrapy crawl example

三、高效数据提取技巧

1. 使用 CSS 和 XPath 选择器

Scrapy 提供了便捷的 CSS 和 XPath 选择器,可以轻松提取网页内容:

  • CSS 示例
titles = response.css('h1::text').getall()
  • XPath 示例
titles = response.xpath('//h1/text()').getall()

2. 使用 Item 提取结构化数据

定义一个 Item 来存储爬取的数据:

# items.py
import scrapy

class ExampleItem(scrapy.Item):
    title = scrapy.Field()
    url = scrapy.Field()

在 Spider 中使用 Item

from myproject.items import ExampleItem

def parse(self, response):
    item = ExampleItem()
    item['title'] = response.css('h1::text').get()
    item['url'] = response.url
    yield item

四、提升爬虫性能的设置和优化

1. 配置并发与延迟

settings.py 中配置以下参数来提升爬取速度:

# 设置并发数
CONCURRENT_REQUESTS = 16

# 降低爬取延迟
DOWNLOAD_DELAY = 0.5

# 每个域名的并发请求数
CONCURRENT_REQUESTS_PER_DOMAIN = 8

2. 启用持久化功能

Scrapy 提供了断点续爬的功能,可以通过以下命令启用:

scrapy crawl example --set JOBDIR=crawls/example

3. 启用缓存

对于开发和调试阶段,可以启用缓存以减少网络请求:

HTTPCACHE_ENABLED = True
HTTPCACHE_EXPIRATION_SECS = 86400  # 缓存 1 天

五、处理反爬的常见技巧

1. 设置 User-Agent

为避免被目标网站屏蔽,可以设置 User-Agent

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'

2. 使用代理

通过设置代理来隐藏真实 IP:

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 543,
}

PROXY_POOL = [
    'http://123.123.123.123:8080',
    'http://111.111.111.111:8080',
]

import random

class ProxyMiddleware:
    def process_request(self, request, spider):
        request.meta['proxy'] = random.choice(PROXY_POOL)

3. 模拟浏览器行为

启用 scrapy-playwrightscrapy-selenium 模拟浏览器行为,处理 JavaScript 渲染的网站:

pip install scrapy-playwright

配置 settings.py

DOWNLOAD_HANDLERS = {
    'http': 'scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler',
    'https': 'scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler',
}

PLAYWRIGHT_BROWSER_TYPE = 'chromium'

六、数据存储与导出

1. 导出为 CSV 或 JSON 文件

运行爬虫时直接导出数据:

scrapy crawl example -o output.json

2. 使用 Pipeline 存储到数据库

编辑 pipelines.py,将数据存入数据库:

import sqlite3

class SQLitePipeline:

    def open_spider(self, spider):
        self.connection = sqlite3.connect('example.db')
        self.cursor = self.connection.cursor()
        self.cursor.execute('CREATE TABLE IF NOT EXISTS data (title TEXT, url TEXT)')

    def close_spider(self, spider):
        self.connection.close()

    def process_item(self, item, spider):
        self.cursor.execute('INSERT INTO data (title, url) VALUES (?, ?)', (item['title'], item['url']))
        self.connection.commit()
        return item

启用 Pipeline:

ITEM_PIPELINES = {
    'myproject.pipelines.SQLitePipeline': 300,
}

七、监控与调试

1. 使用 scrapy shell 调试

scrapy shell 'http://example.com'

在交互环境中测试选择器和解析逻辑。

2. 启用日志记录

settings.py 中设置日志级别:

LOG_LEVEL = 'INFO'

八、分布式爬虫的实现

通过 scrapy-redis 实现分布式爬虫,使用 Redis 存储任务队列和爬取状态。

安装 scrapy-redis

pip install scrapy-redis

配置爬虫使用 Redis 队列:

# settings.py
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
SCHEDULER_PERSIST = True
REDIS_URL = 'redis://localhost:6379'

在 Spider 中继承 RedisSpider

from scrapy_redis.spiders import RedisSpider

class DistributedSpider(RedisSpider):
    name = 'distributed'
    redis_key = 'distributed:start_urls'

    def parse(self, response):
        yield {'url': response.url}

建议

Scrapy 是一个高效的爬虫框架,通过灵活的配置和扩展,可以轻松应对各种复杂场景。从基础的 Spider 编写到性能优化,再到分布式爬取,Scrapy 都为开发者提供了丰富的工具链。在实际项目中,根据具体需求选择合适的功能,可以最大化 Scrapy 的潜力。

九、Scrapy 实战:实现一个新闻爬虫

为了更好地理解 Scrapy 的使用,下面将通过一个实战案例,演示如何构建一个新闻爬虫,爬取指定新闻网站的文章标题、链接以及发布日期。我们将结合前面讲解的技巧,确保爬虫高效、稳定并能处理反爬措施。

1. 确定目标网站

假设我们要爬取一个新闻网站(例如 example.com),并提取以下信息:

  • 文章标题
  • 文章链接
  • 文章发布日期

2. 创建 Scrapy 项目

首先,创建 Scrapy 项目:

scrapy startproject news_scraper

进入项目目录:

cd news_scraper

3. 编写 Spider

使用 scrapy genspider 创建一个新的爬虫:

scrapy genspider news_spider example.com

编辑 news_spider.py,编写爬虫逻辑:

import scrapy

class NewsSpider(scrapy.Spider):
    name = "news_spider"
    start_urls = ['http://example.com/news']

    def parse(self, response):
        for article in response.css('div.article'):
            title = article.css('h2 a::text').get()
            link = article.css('h2 a::attr(href)').get()
            date = article.css('span.date::text').get()

            yield {
                'title': title,
                'link': response.urljoin(link),
                'date': date
            }

        # 翻页逻辑
        next_page = response.css('a.next_page::attr(href)').get()
        if next_page:
            yield response.follow(next_page, self.parse)

4. 运行爬虫

运行爬虫并输出结果到 JSON 文件:

scrapy crawl news_spider -o news.json

5. 处理反爬

目标网站可能会有反爬机制,如 IP 限制、请求频率控制等。我们可以通过以下方式进行优化:

1. 设置 User-Agent

修改 settings.py 文件,设置 User-Agent 伪装成真实浏览器:

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
2. 设置请求延迟

通过配置 DOWNLOAD_DELAY,降低爬取速度,减少被封禁的风险:

DOWNLOAD_DELAY = 1  # 1秒的延迟
CONCURRENT_REQUESTS = 8  # 设置并发请求数
3. 使用代理池

为了避免因频繁请求同一网站而被封,我们可以使用代理池。首先,安装 scrapy-proxies 库:

pip install scrapy-proxies

然后,在 settings.py 中配置代理:

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 543,
}

PROXY_POOL = [
    'http://123.123.123.123:8080',
    'http://111.111.111.111:8080',
    # 添加更多代理地址
]

import random

class ProxyMiddleware:
    def process_request(self, request, spider):
        request.meta['proxy'] = random.choice(PROXY_POOL)
4. 启用缓存

为了提高开发效率,避免频繁请求,启用缓存:

HTTPCACHE_ENABLED = True
HTTPCACHE_EXPIRATION_SECS = 86400  # 缓存1天

6. 数据存储与清洗

1. 存储到数据库

如果数据量较大,可以将数据存储到数据库中,而不是直接导出到文件。我们可以通过 Scrapy 的 Pipeline 功能将数据存入 SQLite 数据库。

首先,创建一个数据库 Pipeline:

# pipelines.py
import sqlite3

class SQLitePipeline:

    def open_spider(self, spider):
        self.connection = sqlite3.connect('news.db')
        self.cursor = self.connection.cursor()
        self.cursor.execute('CREATE TABLE IF NOT EXISTS news (title TEXT, link TEXT, date TEXT)')

    def close_spider(self, spider):
        self.connection.close()

    def process_item(self, item, spider):
        self.cursor.execute('INSERT INTO news (title, link, date) VALUES (?, ?, ?)', 
                            (item['title'], item['link'], item['date']))
        self.connection.commit()
        return item

settings.py 中启用该 Pipeline:

ITEM_PIPELINES = {
    'news_scraper.pipelines.SQLitePipeline': 1,
}
2. 数据清洗

如果从网页提取的数据不完全或者需要处理额外的字段(如日期格式化),可以在 Pipeline 中进行数据清洗。例如,将日期格式化为统一的标准格式:

from datetime import datetime

class DateFormatPipeline:

    def process_item(self, item, spider):
        item['date'] = datetime.strptime(item['date'], '%Y-%m-%d').strftime('%d/%m/%Y')
        return item

settings.py 中启用:

ITEM_PIPELINES = {
    'news_scraper.pipelines.DateFormatPipeline': 2,
    'news_scraper.pipelines.SQLitePipeline': 1,
}

7. 分布式爬虫(可选)

如果爬取的新闻量巨大,可以使用 scrapy-redis 来实现分布式爬虫。通过 Redis 存储 URL 队列并在多个爬虫实例之间共享任务。

首先,安装 scrapy-redis

pip install scrapy-redis

settings.py 中进行配置:

DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
SCHEDULER_PERSIST = True
REDIS_URL = 'redis://localhost:6379'

修改 Spider 以使用 Redis:

from scrapy_redis.spiders import RedisSpider

class RedisNewsSpider(RedisSpider):
    name = "redis_news_spider"
    redis_key = 'news:start_urls'

    def parse(self, response):
        for article in response.css('div.article'):
            title = article.css('h2 a::text').get()
            link = article.css('h2 a::attr(href)').get()
            date = article.css('span.date::text').get()
            yield {'title': title, 'link': link, 'date': date}

十、总结与展望

在这篇博客中,我们通过实战示例讲解了如何使用 Scrapy 构建高效的新闻爬虫项目。通过合理的配置、性能优化、反爬机制处理及数据存储管理,我们能确保爬虫高效、稳定并能够适应大规模的数据抓取需求。

关键技巧总结:

  • 高效的数据提取:合理使用 CSS 和 XPath 选择器,提取结构化数据。
  • 性能优化:通过设置并发、延迟、使用代理池等手段提升爬虫效率。
  • 数据存储:将爬取的数据存储到数据库或文件中,确保数据持久化。
  • 反爬机制:通过伪装 User-Agent、使用代理、模拟浏览器等手段绕过反爬措施。
  • 分布式爬取:通过 Scrapy-Redis 实现分布式爬虫,处理大规模数据抓取任务。

通过这些技巧,你可以开发出一个高效、稳定、能够应对复杂挑战的 Scrapy 爬虫项目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2243128.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

预处理(1)(手绘)

大家好,今天给大家分享一下编译器预处理阶段,那么我们来看看。 上面是一些预处理阶段的知识,那么明天给大家讲讲宏吧。 今天分享就到这里,谢谢大家!!

ZYNQ程序固化——ZYNQ学习笔记7

一、ZYNQ启动过程 二、 SD卡启动实操 1、对ZYNQ进行配置添加Flash 2、添加SD卡 3、重新生成硬件信息 4、创建vitis工程文件 5、勾选板级支持包 6、对系统工程进行整体编译,生成两个Debug文件,如图所示。 7、插入SD卡,格式化为 8、考入BOOT.…

FPGA实现PCIE采集电脑端视频转SFP光口万兆UDP输出,基于XDMA+GTX架构,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案10G Ethernet Subsystem实现万兆以太网物理层方案 3、PCIE基础知识扫描4、工程详细设计方案工程设计原理框图电脑端视频PCIE视频采集QT上位机XDMA配置及使用XDMA中断模块FDMA图像缓存UDP视频组包发送UDP协议栈MAC…

Mongo数据库集群搭建

目录 1、Mongo集群优势 1.1 高可用性 1.2 水平扩展性 1.3 高性能 1.4 灵活的架构设计 1.5 数据安全 1.6 管理与监控 2、下载指定操作系统版本包 3、部署和验证工作 3.1 准备配置文件及依赖 3.2 启动第一个节点 3.3 部署更多的节点 3.4 初始化副本集 3.5 设置管理…

创建vue3项目步骤

脚手架创建项目: pnpm create vue Cd 项目名称安装依赖:Pnpm iPnpm Lint:修复所有文件风格 ,不然eslint语法警告报错要双引号Pnpm dev启动项目 拦截错误代码提交到git仓库:提交前做代码检查 pnpm dlx husky-in…

C语言项⽬实践-贪吃蛇

目录 1.项目要点 2.窗口设置 2.1mode命令 2.2title命令 2.3system函数 2.Win32 API 2.1 COORD 2.2 GetStdHandle 2.3 CONSOLE_CURSOR_INFO 2.4 GetConsoleCursorInfo 2.5 SetConsoleCursorInfo 2.5 SetConsoleCursorPosition 2.7 GetAsyncKeyState 3.贪吃蛇游戏设…

nfs服务器--RHCE

一,简介 NFS(Network File System,网络文件系统)是FreeBSD支持的文件系统中的一种,它允许网络中的计 算机(不同的计算机、不同的操作系统)之间通过TCP/IP网络共享资源,主要在unix系…

自动化运维(k8s):一键获取指定命名空间镜像包脚本

前言:脚本写成并非一蹴而就,需要不断的调式和修改,这里也是改到了7版本才在 生产环境 中验证成功。 该命令 和 脚本适用于以下场景:在某些项目中,由于特定的安全或政策要求,不允许连接到你的镜像仓库。然而…

HuggingFace:基于YOLOv8的人脸检测模型

个人操作经验总结 1、YOLO的环境配置 github 不论base环境版本如何,建议在conda的虚拟环境中安装 1.1、创建虚拟环境 conda create -n yolov8-face python3.9conda create :创建conda虚拟环境, -n :给虚拟环境命名的…

Unet++改进28:添加PPA(2024最新改进方法)|多分支特征提取策略,捕获不同尺度和层次的特征信息。

本文内容:添加PPA 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 红外小目标检测是一项重要的计算机视觉任务,涉及对红外图像中通常只有几个像素的微小目标进行识别和定位。然而,由于红外图像中物体的体积小,背景一般比较复杂,这给红外图像的识别带来…

CTF攻防世界小白刷题自学笔记13

1.fileinclude,难度:1,方向:Web 题目来源:宜兴网信办 题目描述:无 给一下题目链接:攻防世界Web方向新手模式第16题。 打开一看给了很多提示,什么language在index.php的第九行,flag在flag.php中,但事情显…

同三维T610UDP-4K60 4K60 DP或HDMI或手机信号采集卡

1路DP/HDMI/TYPE-C(手机/平板等)视频信号输入1路MIC1路LINE OUT,带1路HDMI环出,USB免驱,分辨率4K60,可采集3路信号中其中1路,按钮切换,可采集带TYPE-C接口的各品牌手机/平板/笔记本电脑等 同三维…

小程序如何完成订阅

小程序如何完成订阅 参考相关文档实践问题处理授权弹窗不再触发引导用户重新授权 参考相关文档 微信小程序实现订阅消息推送的实现步骤 发送订阅消息 小程序订阅消息(用户通过弹窗订阅)开发指南 实践 我们需要先选这一个模板,具体流程参考…

解决Xeyes: Error can‘t open display,远程X无法连通问题。

一、问题分析 提前申明: 本次实验使用REHL 8 进行操作! 客户机 A 为X-Client ,即远程X的客户端。 服务机 B 为X-Server,即远程X的服务端。 问题的所有操作均在已经配置好Xorg的前提下进行的,不知道不配置会有什么影响&…

JS学习日记(jQuery库)

前言 今天先更新jQuery库的介绍,它是一个用来帮助快速开发的工具 介绍 jQuery是一个快速,小型且功能丰富的JavaScript库,jQuery设计宗旨是“write less,do more”,即倡导写更少的代码,做更多的事&#xf…

华为HCIP——MSTP/RSTP与STP的兼容性

一、MSTP/RSTP与STP的兼容性的原理: 1.BPDU版本号识别:运行MSTP/RSTP协议的交换机会根据收到的BPDU(Bridge Protocol Data Unit,桥协议数据单元)版本号信息自动判断与之相连的交换机的运行模式。如果收到的是STP BPDU…

基于YOLOv8深度学习的智慧课堂学生专注度检测系统(PyQt5界面+数据集+训练代码)

本研究提出了一种基于YOLOv8深度学习的智慧课堂学生专注度检测系统,旨在实现对课堂中学生专注度的实时分析与评估。随着智慧教育的快速发展,学生的课堂表现和专注度成为评估学习效果的重要因素之一。然而,传统的专注度评估方法往往依赖于主观…

【汇编】c++游戏开发

由一起学编程创作的‘C/C项目实战:2D射击游戏开发(简易版), 440 行源码分享来啦~’: C/C项目实战:2D射击游戏开发(简易版), 440 行源码分享来啦~_射击c-CSDN博客文章浏览…

QT_CONFIG宏使用

时常在Qt代码中看到QT_CONFIG宏,之前以为和#define、DEFINES 差不多,看了定义才发现不是那么回事,定义如下: 看注释就知道了QT_CONFIG宏,其实是:实现了一个在编译时期安全检查,检查指定的Qt特性…

Area-Composition模型部署指南

一、介绍 本模型可以通过输入不同的提示词,然后根据各部分提示词进行融合生成图片。如下图: 此图像包含 4 个不同的区域:夜晚、傍晚、白天、早晨 二、部署 环境要求: 最低显存:10G 1. 部署ComfyUI 本篇的模型部署…