介绍
Scrapy是一个用于爬取网站数据的Python框架。它提供了一套强大而灵活的工具,使开发者能够轻松地创建和管理爬虫,从而从网站中提取所需的信息。框架要求Python的版本 3.8+
特点
- 结构化的框架:
Scrapy提供了一个清晰的结构,将爬虫的不同部分组织起来,包括爬虫代码、中间件、下载器等。这种结构使得代码模块化,易于维护和扩展。 - 异步处理:
Scrapy使用Twisted异步网络引擎,能够并行处理多个请求,提高爬取效率。这使得Scrapy适用于大规模的数据抓取任务。 - 内置的选择器:
Scrapy内置了强大的选择器(XPath和CSS选择器),使得开发者能够方便地从HTML或XML文档中提取所需的数据。 - 中间件支持: 可以通过中间件进行请求和响应的预处理,例如添加代理、修改
User-Agent等,从而提高爬虫的灵活性和适应性。 - 自动限速:
Scrapy支持自动限速功能,可以设置每秒发送请求的数量,防止对目标服务器造成过大的负担,也有助于规避反爬虫策略。 - 扩展性:
Scrapy提供了丰富的插件系统,允许开发者通过编写扩展或中间件来自定义爬虫的行为,使其更适应特定的需求。 - 数据存储: 支持将爬取到的数据存储到多种格式,包括
JSON、CSV、XML等,也可以存储到数据库中。 - 调试工具:
Scrapy提供了命令行工具和图形界面(Scrapy Shell)用于调试和测试爬虫,方便开发者查看和验证提取的数据。
安装
# 安装
$ pip install scrapy
# 查看版本
$ scrapy version
Scrapy 2.11.0
子命令
bench: 运行快速的性能基准测试,用于评估Scrapy的性能。check: 用于检查Scrapy项目的代码并执行一些基本的检查,以确保项目的结构和配置正确;crawl: 用于启动一个爬虫,如:scrapy crawl xxx;edit: 用于编辑爬虫代码,可以指定使用哪个编辑器打开,一般不用;fetch: 使用Scrapy下载器获取指定URL的内容,并将其显示在命令行中。用于测试单个URL的下载和解析。genspider: 生成新的爬虫spider,使用预定义的模板来快速创建新的爬虫项目。可以指定爬虫的名称、域名等参数。list: 用于列出可用的爬虫,需求在爬虫项目目录下执行;runspider: 运行一个独立的爬虫,而不必创建整个Scrapy项目。这是一种简便的方式来测试或运行单个爬虫文件。settings: 获取当前Scrapy项目的设置值。可以查看当前项目的配置信息。shell: 启动一个交互式的Scrapy控制台,方便开发者在命令行中测试和调试爬虫代码,查看和提取数据。startproject: 创建一个新的Scrapy项目。该命令将生成一个包含基本结构的新目录,包括默认的设置、爬虫模板等。version: 显示当前安装的Scrapy版本号。view: 在默认的Web浏览器中打开指定的URL,以查看网页内容。可以帮助开发者直观地查看网页,了解其结构。
初始化项目
scrapy提供了类似脚手架子命令:scrapy startproject xxx,可以用来直接创建一个项目,免去我们一些繁琐工作;
startproject: 创建一个新的Scrapy项目。该命令将生成一个包含基本结构的新目录,包括默认的设置、爬虫模板等。
创建项目
$ scrapy startproject scrapy_study_demo
# 添加示例
$ cd scrapy_study_demo
$ scrapy genspider 爬虫名称 域名
项目目录介绍
scrapy_study_demo # 项目目录
├── scrapy.cfg # 配置文件
└── scrapy_study_demo # 项目的Python包
├── items.py # 定义爬取的数据结构(Item)
├── middlewares.py# 中间件
├── pipelines.py # 管道
├── settings.py #项目的配置文件
└── spiders # 存放爬虫代码的目录
└── example.py # scrapy genspider example example.com 创建的实例代码
items.py: 定义爬取的数据结构(Item)。每个Item对应爬虫要提取的信息的数据模型。middlewares.py: 包含中间件的文件。中间件是在Scrapy引擎和下载器之间处理请求和响应的钩子。pipelines.py: 包含管道的文件。管道负责处理爬取到的Item,例如存储到数据库或文件。settings.py: 项目的配置文件,包含各种配置选项,如下载延迟、用户代理等
实战示例
下面以爬取网易音乐:【热歌榜Top200】为实战示例,仅供学习使用,勿做其他用途~
访问地址:https://music.163.com/#/discover/toplist?id=3778678
//创建爬虫 名称 wy_music 需要爬的网页 https://music.163.com/#/discover/toplist?id=3778678
$ scrapy genspider wy_music https://music.163.com/#/discover/toplist?id=3778678
Created spider 'wy_music' using template 'basic' in module:
scrapy_study_demo.spiders.wy_music
上述命令会创建文件:scrapy_study_demo/spiders/,并生成填充一些代码,个人感觉代码生成的有写瑕疵,就改了改wy_music.py
import scrapy
from typing import Any
from scrapy.http import Response
class WyMusicSpider(scrapy.Spider):
name = "wy_music"
allowed_domains = ["music.163.com"]
start_urls = ["https://music.163.com/#/discover/toplist?id=3778678"]
def parse(self, response: Response, **kwargs: Any):
print('网页内容:', response.text)
pass
crawl: 用于启动一个爬虫,如:scrapy crawl xxx;成功打印了html的内容,由于内容太长就不粘贴了。
解析语法
到这一步基本工作完成了,但是还有主要工作,就是解析网页内容,scrapy框架提供了两种机制,分别是基于XPath和css的表达式
这里有个小插曲,网页有点特殊因为是iframe嵌套的,所以F12查看按照XPath和css方式去查找都不行,页面元素都是动态生成的,但是在查看页面源码时偶然间发现居然有个大的json字符串在里面,通过复制格式化查看居然就是咱们要找的数据........


这样我们就方便多了,直接获取内容解析就可以了,根据json结构先尝试打印歌名试试
class WyMusicSpider(scrapy.Spider):
name = "wy_music"
allowed_domains = ["music.163.com"]
start_urls = ["https://music.163.com/discover/toplist?id=3778678"]
def parse(self, response: Response):
#通过css获取标签内容
json_str = response.css('#song-list-pre-data::text').getall()
#转化成json列表
data_list = json.loads(json_str[0])
for str in data_list:
#尝试打印字段内容
print(str['name'])
顺利打印出了歌名

下一步咱们把自己想要内容保留下来,首先我们需要一个容器来装这些数据,创建item
Item ,为了定义常用的输出数据,Scrapy 提供了 Item 类。Item 对象是种简单的容器,保存了爬取到得数据。 其提供了类似于词典(dictionary-like)的API以及用于声明可用字段的简单语法。
我们在工程目录下可以看到一个 items 文件,我们可以更改这个文件或者创建一个新的文件来定义我们的 item。
此时可以将item.py修改如下:
import scrapy
class demoItem(scrapy.Item):
# define the fields for your item here like:
id = scrapy.Field() # id
artists = scrapy.Field() # 作者
name = scrapy.Field() # 歌名
picUrl = scrapy.Field() # 封面
duration = scrapy.Field() # 时长
pass
在创建完 item 文件后我们可以通过类似于词典(dictionary-like)的API以及用于声明可用字段的简单语法。 常用方法如下:
#定义一个item
course = demoItem()
#赋值
course['id'] = "1"
#取值
course['id']
course.get('id')
#获取全部键
course.keys()
#获取全部值
course.items()
有了容器可以完整来一次了
from scrapy_study_demo.items import demoItem #引用容器
class WyMusicSpider(scrapy.Spider):
name = "wy_music"
allowed_domains = ["music.163.com"]
start_urls = ["https://music.163.com/discover/toplist?id=3778678"]
def parse(self, response: Response):
json_str = response.css('#song-list-pre-data::text').getall()
data_list = json.loads(json_str[0])
item = demoItem() #声明容器
for str in data_list:
# print(timedelta(seconds = int(str['duration']/1000)))
item['id'] = str['id']
item['name'] = str['name']
item['duration'] = timedelta(seconds = int(str['duration']/1000))
str_list = str['artists']
artStr = ''
for art in str_list:
artStr+=(art['name']+'/')
item['artists'] = artStr[:-1]
print(item['artists'])
if str['album']['picUrl']!='':
item['picUrl'] = str['album']['picUrl']
yield item
运行它可以得到到我们想要的数据了
数据保存
拿到了以后我们现在只是打印出来,那怎样保存呢?
Scrapy 提供的 Feed Exports 可以轻松将抓取结果输出。 例如,我们想将上面的结果保存成 csv 文件,可以在命令 窗口中执行如下命令:
scrapy crawl wy_music -o myspider.csv
命令运行后,项目内多了一个 myspider.csv 文件,文件包含了刚才抓取的所有内容,内容是 csv 格式,如下图:

输出格式还支持很多种,例如 json、 xml 、 pickle 、 marshal 等。 下面命令对应的输出分别为 json 、 xml 、 pickle 、 marshal 格式以及句远程输出。
scrapy crawl my_music -o myspider.json
scrapy crawl my_music -o myspider.xml
scrapy crawl my_music -o myspider.pickle
scrapy crawl my_music -o myspider.marshal
scrapy crawl my_music -o ftp://user:path@ftp.example.com/path/to/myspider.csv
其中, ftp输出需要正确配置用户名、密码、地址、输出路径,否则会报错。
通过 Scrapy 提供的 Feed Exports,我们可以轻松地输出抓取结果到文件。对于一些小型项目来说,这应该足够了。不过如果想要更复杂的输出,如输出到数据库等,我们可以使用 ItemPileline 来完成。
好了这次尝试Scrapy就先使用到这里吧,后面有时间了会再继续更新相关内容。
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://mi-blog.cn/index.php/2021/08/15/python%e5%ad%a6%e4%b9%a0-scrapy/