地球上最好用的爬虫框架:Scrapy:

作者 : admin 本文共3575个字,预计阅读时间需要9分钟 发布时间: 2024-06-16 共1人阅读

基本流程:

了解Scrapy 爬虫框架的工作流程:

地球上最好用的爬虫框架:Scrapy:插图

scrapy中, 具体工作流程是这样的:

首先第一步 当爬虫引擎启动后, 引擎会到 spider 中获取 start_url 然后将其封装为一个request对象, 交给调度器,  这个调度器中存的是一个又一个的待请求的url request对象, 然后调度器会通过引擎将请求对象交给 下载器  下载器获取到请求对象后, 发送请求,获取响应, 然后将获取的响应封装成一个响应对象 response 后通过引擎再交给spider 来进行数据解析, 数据的解析结果如果是 Url, 则通过引擎继续交给调度器, 如果是数据, 则会通过引擎,将数据交给管道, 这就是scrapy的工作流程,

下载:

pip install scrapy

创建爬虫项目:

在终端中使用scrapy命令来创建一个爬虫项目:

scrapy startproject 项目名字

 当我们使用命令完成创建项目的时候, scrapy会自动给我们创建一个有关 项目名  的文件夹:

地球上最好用的爬虫框架:Scrapy:插图(1)

第一个 game 只是scrapy 创建的项目文件, 也就是项目根目录。

第二个game 目录则是我们的scrapy项目了,  项目目录下的 spiders 目录就是 有关 spider 爬虫脚本的目录

items: 暂时先不了解

middlewares: 中间件

pipelines: 管道, 所有爬虫获取到的数据最终都会到管道来

settings: 项目配置文件

创建爬虫:

使用scrapy命令创建爬虫, 但在运行命令之前,需要 cd 进入到爬虫项目中

scrapy genspider

scrapy genspider myspider baidu.com

然后你会发现在spiders目录下,会多出一个爬虫脚本,点开脚本 :

地球上最好用的爬虫框架:Scrapy:插图(2) 你会发现scrapy为我们创建了一个爬虫类, 集成之Spider

name 则是爬虫的名字

allowed_domains 则是允许爬取的域名, 除此以外的域名都会被过滤掉

start_urls 则就是起始URL了

而此爬虫类中, 还提供了一个 parse 方法, 此方法就是用来解析获取的响应结果的,

启动爬虫:

启动爬虫也很简单, 使用命令启动爬虫

scrapy crawl 爬虫名字

你会看到控制台打印很多东西, 不用着急, 这只是scrapy的输出日志而已, 我们可以通过命令行或者在settings中配置一下日志输出级别:

楼主这里是在settings 文件中配置的:

地球上最好用的爬虫框架:Scrapy:插图(3)

加上这句, 配置日志级别为 warning, 那么控制台就只能打印 warning及以上级别的信息了

数据管道:

从爬虫中解析出的数据, 返回给引擎后,由引擎交给数据管道进行处理, 我们可以定义多个数据管道,用来对数据进行不同的存储方式

地球上最好用的爬虫框架:Scrapy:插图(4)

在pipelines 中定义的所有类都是管道类, 它拥有一个process_item 的方法, 形参 item 就是我们要处理的数据, 而spider, 见名之意, 则是爬虫

定义好管道后, 还需要到settings 配置文件中启用管道:

地球上最好用的爬虫框架:Scrapy:插图(5)

在settings文件中, 找到此字典,把注释打开, 对应的 key 则是定义好的管道类, 而value 则是 “权重” , 意思就是, 这个值越小, 执行的优先权则越高。

管道:

scrapy 中, spider模块提取出的数据就会交给数据管道进一步处理,先看一下spider中的代码:

地球上最好用的爬虫框架:Scrapy:插图(6)

例如这里, 定义了一个爬取彩票网站的spider爬虫, 修改好起始的URL, 就可以在parse 方法中提取解析的数据, 我们可以在scrapy中使用 xpath,css 选择器 等提取规则来提取数据, 这里需要注意的是, xpath,css选择器等 在scrapy中已经封装好了,不需要在额外的下载 lxml, bs4 了

Item:

 在scrapy中, 可以使用scrapy封装好的数据对象Item来进行数据存储,当然, 你也可以再定义一个字典,来封装数据,但是这样做不好。 当我们的爬虫项目代码量很多的时候, 会很容易出一些不好找的低级bug, 点开 items.py 文件:

地球上最好用的爬虫框架:Scrapy:插图(7)

可以看到scrapy为我们自动生成了一个继承自 Item 的类, 我们可以在这个类中定义好要封装的数据字段, 然后在spider中使用, 在spider中使用起来也是很简单的, 直接创建该类的对象,然后使用 key: value 的形式来封装数据, 因为 Item 本质上就是一个 dict 类型。地球上最好用的爬虫框架:Scrapy:插图(8)

使用了scrapy中的 Item 对象来管理数据, 那么 cai[“date”] 这个 key 值必须和 Item 类中定义好的字段一模一样, 不然会报错,例如:

地球上最好用的爬虫框架:Scrapy:插图(9)地球上最好用的爬虫框架:Scrapy:插图(10)

这样我们在spider中封装数据的时候, 因为手抖写错了 key 值, 那么scrapy框架就会友好的提示我们bug 所在, 这样会很友好。

在返回数据这里, scrapy中一般都是使用yield 关键字来向引擎返回数据。

存储数据:

在爬虫中, 我们可以将数据通过管道存储到 csv 文件, 数据库, 普通文本文件等。

来看代码:

Csv:

地球上最好用的爬虫框架:Scrapy:插图(11)

 在这个管道中, 我重写了两个方法, 分别是 open_spider,  和 close_spider,  管道启动的时候, 会先调用 open_spider, 然后 再调用 process_item 方法来进行数据存储, 最后调用 close_spider, 由此看来, 我们可以在open_spider 中进行连接的初始化, 例如打开一个文件,或者初始化数据库的链接信息, 当所有数据都存储处理完成后, 在close_spider 中关闭所有链接来做善后处理, 这样就不会造成重复的打开,关闭,打开,关闭的IO 问题了。

Mysql:

存储到mysql数据库中,我们可以重新定义一个管道类, 然后将这个管道类注册到settings中:

地球上最好用的爬虫框架:Scrapy:插图(12)

class CaipiaoMySQLPipeline:
    """ 存储mysql """

    def open_spider(self, spider):
        self.conn = pymysql.connect(
            host="localhost",
            port=3306,
            user="root",
            password="root",
            database="spider"
        )

    def process_item(self, item, spider):
        try:
            cursor = self.conn.cursor()
            sql = "insert into caipiao(date_time, red_ball, blue_ball) values (%s, %s, %s)"
            cursor.execute(sql, (item["date"], "_".join(item["red_ball"]), item['blue_ball']))
            self.conn.commit()
        except:
            self.conn.rollback()
        finally:
            if cursor:
                cursor.close()
        return item

    def close_spider(self, spider):
        self.conn.close()
MongoDB:

class CaipiaoMongoDBPipeline:
    """ 存储数据到 MongoDB """

    def open_spider(self, spider):
        # 初始化 MongoDB 连接
        self.client = pymongo.MongoClient(host="localhost", port=27017, username="root", password="root")
        db = self.client["spider"]
        self.collection = db["caipiao"]

    def process_item(self, item, spider):
        # 插入文档到集合,并处理潜在的插入错误
        self.collection.insert_one({
            "date": item["date"],
            "red_ball": item["red_ball"],
            "blue_ball": item["blue_ball"]
        })

        return item

    def close_spider(self, spider):
        # 关闭 MongoDB 连接
        self.client.close()
scrapy.Request:

 网页的每个页面都是不一样的, 例如我们想要在一些图片网站上抓取一些图片, 那么首先我们需要先获取网站的图片列表页, 然后在逐个点击列表页的每张图片进入到图片的详情页, 这样在详情页才能提取出高清质量的图片链接信息,再下载高清图片。 如果遇到这种情况, 怎么处理呢?

地球上最好用的爬虫框架:Scrapy:插图(13)

 当我们在scrapy 提供的 parse方法中提取到了列表页之后, 可以使用scrapy 提供的Request 对象, 将列表页中的详情页url 拼接完毕后使用Request 对象封装成一个请求对象,回顾scrapy 的工作流程, 如果spider 返回给引擎的是一个请求对象,那么引擎会将这个请求对象交给调度器排队继续发送请求, 这个Request对象中的 callback 形参指定的就是一个方法, 因为发送请求必须就得有响应, 所以这里可以传递一个回调方法专门去处理该响应的结果!

中间件:

本站无任何商业行为
个人在线分享 » 地球上最好用的爬虫框架:Scrapy:
E-->