Python学习-Scrapy

米阳 2021-8-15 624 8/15

介绍

Scrapy是一个用于爬取网站数据的Python框架。它提供了一套强大而灵活的工具,使开发者能够轻松地创建和管理爬虫,从而从网站中提取所需的信息。框架要求Python的版本 3.8+

特点

  1. 结构化的框架:Scrapy提供了一个清晰的结构,将爬虫的不同部分组织起来,包括爬虫代码、中间件、下载器等。这种结构使得代码模块化,易于维护和扩展。
  2. 异步处理:Scrapy使用Twisted异步网络引擎,能够并行处理多个请求,提高爬取效率。这使得Scrapy适用于大规模的数据抓取任务。
  3. 内置的选择器:Scrapy内置了强大的选择器(XPath和CSS选择器),使得开发者能够方便地从HTMLXML文档中提取所需的数据。
  4. 中间件支持: 可以通过中间件进行请求和响应的预处理,例如添加代理、修改User-Agent等,从而提高爬虫的灵活性和适应性。
  5. 自动限速:Scrapy支持自动限速功能,可以设置每秒发送请求的数量,防止对目标服务器造成过大的负担,也有助于规避反爬虫策略。
  6. 扩展性:Scrapy提供了丰富的插件系统,允许开发者通过编写扩展或中间件来自定义爬虫的行为,使其更适应特定的需求。
  7. 数据存储: 支持将爬取到的数据存储到多种格式,包括JSON、CSV、XML等,也可以存储到数据库中。
  8. 调试工具: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字符串在里面,通过复制格式化查看居然就是咱们要找的数据........

Python学习-Scrapy

Python学习-Scrapy

这样我们就方便多了,直接获取内容解析就可以了,根据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'])

顺利打印出了歌名

Python学习-Scrapy

下一步咱们把自己想要内容保留下来,首先我们需要一个容器来装这些数据,创建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 格式,如下图:

Python学习-Scrapy Python学习-Scrapy

输出格式还支持很多种,例如 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就先使用到这里吧,后面有时间了会再继续更新相关内容。

 

 

 

- THE END -

米阳

3月17日21:05

最后修改:2025年3月17日
0

非特殊说明,本博所有文章均为博主原创。