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

用 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__.pyitems.py        # 定义数据结构middlewares.py  # 定义中间件pipelines.py    # 定义数据管道settings.py     # 项目设置spiders/        # 存放爬虫文件

2. 编写 Spider

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

创建一个简单的爬虫:

scrapy genspider example example.com

编辑 example.py

import scrapyclass 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 scrapyclass ExampleItem(scrapy.Item):title = scrapy.Field()url = scrapy.Field()

在 Spider 中使用 Item

from myproject.items import ExampleItemdef parse(self, response):item = ExampleItem()item['title'] = response.css('h1::text').get()item['url'] = response.urlyield 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 randomclass 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 sqlite3class 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 RedisSpiderclass 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 scrapyclass 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 randomclass 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 sqlite3class 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 datetimeclass 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 RedisSpiderclass 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.rhkb.cn/news/472830.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中volatile 类型变量提供什么保证?能使得一个非原子操作变成原子操作吗?

大家好,我是锋哥。今天分享关于【java中volatile 类型变量提供什么保证?能使得一个非原子操作变成原子操作吗?】面试题。希望对大家有帮助; java中volatile 类型变量提供什么保证?能使得一个非原子操作变成原子操作吗&…

candence : 通孔焊盘、插装器件封装绘制

通孔焊盘、插装器件封装绘制 以2.54mm 2x10的 排针为例绘制封装 一、 flash 热风焊盘制作 1、新建 2、选择 flash SYMBOL,并设置保存路径 3、add flash 具体参数 花焊盘参数 Inner diameter 通孔直径(1.0mm) 圆形补偿值(0.4mm)1.4mm Outer diameter 通孔直径…

VSCode设置

打开设置页 VSCode打开配置页面,有多种方式: a. 点击左上角 File(文件) -> Preferences (首选项) -> Settings(设置)。 b. 使用快捷键 Ctrl ,(Windows) 或 Cmd ,(Mac)。 c. 点击左下角 Manage(管理) -> Settings(设置)。 VSCode设置页面打…

SpringMVC数据校验、数据格式化处理、国际化设置

SpringMVC数据校验、数据格式化处理、国际化设置 1.数据验证 (1)使用JSR-303验证框架 JSR(Java Specification Requests),意思是Java 规范提案。JSR-303是JAVA EE 6中的一项子规范,叫做Bean Validation。JSR 303&am…

加速 AI 创新:引入 Elastic AI 生态系统

作者:来自 Elastic Alyssa Fitzpatrick, Steve Kearns 生成式人工智能 (Generative AI - GenAI) 正在改变我们所熟知的商业格局。为了简化和加速开发人员构建和部署检索增强生成 (retrieval augmented generation - RAG) 应用程序的方式,Elastic 自豪地宣…

SpringSecurity 鉴权认证入门讲解

​ Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。 ​ 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的比较多,因为相比与Sp…

# ubuntu 安装的pycharm不能输入中文的解决方法

ubuntu 安装的pycharm不能输入中文的解决方法 一、问题描述: 当在 ubuntu 系统中,安装了 pycharm(如:pycharm2016, 或 pycharm2018),打开 pycharm 输入代码时,发现不能正常输入中文,安装的搜狗…

小白进!QMK 键盘新手入门指南

经常玩键盘的伙伴应该都知道,现在的键盘市场可谓是百花齐放,已经不是之前的单一功能产品化时代。我们可以看到很多诸如:机械轴键盘、磁轴键盘、光轴键盘、电感轴键盘,以及可能会上市的光磁轴键盘,更有支持屏幕的、带旋…

EXCEL 或 WPS 列下划线转驼峰

使用场景: 需要将下划线转驼峰,直接在excel或wps中第一行使用公式,然后快速刷整个列格式即可。全列工下划线转为格式,使用效果如下: 操作步骤: 第一步:在需要显示驼峰的一列,复制以…

微信小程序:vant组件库安装步骤

前言:在微信小程序中引用vant组件报错,提示路径不存在,这很有可能是因为没有安装构建vant组件库导致。下面是我整理的安装vant组件库的步骤: 第一步:安装node.js(执行完第一步请重启小程序) 具体步骤请看链接:node.js…

vue3【实战】切换全屏【组件封装】FullScreen.vue

效果预览 原理解析 使用 vueUse 里的 useFullscreen() 实现 代码实现 技术方案 vue3 vite UnoCSS vueUse 组件封装 src/components/FullScreen.vue <template><component:is"tag"click"toggle":class"[!isFullscreen ? i-ep:full-sc…

GPIO相关的寄存器(重要)

目录 一、GPIO相关寄存器概述 二、整体介绍 三、详细介绍 1、端口配置低寄存器&#xff08;GPIOx_CRL&#xff09;&#xff08;xA...E&#xff09; 2、端口配置高寄存器&#xff08;GPIOx_CRH&#xff09;&#xff08;xA...E&#xff09; 3、端口输入数据寄存器&#xff…

【Hadoop实训】Hive 数据操作②

延续上一篇文章&#xff0c;不懂的宝子们请看以下链接&#xff1a; 【Hadoop实训】Hive 数据操作①-CSDN博客 目录 一、Group by 语句 (1)、计算emp表每个部门的平均工资 (2)、计算emp表每个部门中每个岗位的最高工资 二、Having 语句 (1)、求每个部门的平均工资 (2)、求每个…

Vulhub漏洞复现---solr---CVE-2019-17558

漏洞描述 Apache Solr 5.0.0到Apache Solr 8.3.1容易受到通过VelocityResponseWriter执行的远程代码的攻击。Velocity模板可以通过configset ’ Velocity / 目录中的Velocity模板或作为参数提供。用户定义的configset可以包含可呈现的、潜在的恶意模板。参数提供的模板在默认情…

ADS学习笔记 5. 微带天线设计

基于ADS2023 update2 参考书籍&#xff1a;卢益锋老师《ADS射频电路设计与仿真学习笔记》 更多笔记&#xff1a;ADS学习笔记 1. 功率放大器设计ADS学习笔记 2. 低噪声放大器设计ADS学习笔记 3. 功分器设计ADS学习笔记 4. 微带分支定向耦合器设计 目录 0、设计指标 1、微带…

【JAVA】使用IDEA创建maven聚合项目

【JAVA】使用IDEA创建maven聚合项目 1.效果图 2.创建父模块项目 2.1删除父模块下面的src目录以及不需要的maven依赖 3创建子模块项目 3.1右击父模块项目选择Module… 3.2创建子模块 3.3删除子模块下不需要的maven依赖 4.子模块创建完成后引入SpringBoot依赖启动项目

一文详细深入总结服务器选型

1. 题记&#xff1a; 服务器选型工作是项目规划检讨的一项非常重要的工作&#xff0c;本文详细深入总结服务器选型。 2. 服务器基础知识概览 2.1 服务器的定义与功能 2.1 .1 定义 服务器是一种高性能计算机&#xff0c;其设计目的是在网络中提供服务。它可以处理来自多个客…

如何编译 Cesium 源码

如何编译 Cesium 源码 Cesium 是一个开源的 JavaScript 库&#xff0c;用于构建 3D 地球和地图应用程序。它提供了一套强大的 API 和工具&#xff0c;使开发者能够创建丰富的地理空间应用。本文将指导您如何从 GitHub 下载 Cesium 源码&#xff0c;并在本地进行编译。 TilesB…

车载诊断架构 --- 关于DTC的开始检测条件

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…

AI大模型(一):Prompt AI编程

一、Prompt Engineering&#xff0c;提示工程 提示工程也叫指令工程&#xff1a; Prompt是发给大模型的指令&#xff0c;比如【讲个睡前故事】、【用Python写个消消乐游戏】等&#xff1b;本质上大模型相关的工程工作&#xff0c;都是围绕prompt展开的&#xff1b;提示工程门…