python爬虫之Scrapy入门介绍——安装、工作流程、模块介绍

学习参考:Scrapy

1. Scrapy 介绍

1.1 定义和用途

Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,需要实现少量的代码,就能够快速的抓取。
可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。

其最初是为了 网络抓取 所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。

1.2 安装

安装方法

pip install scrapy
# 换源安装
pip install scrapy -i https://py.pi.douban.com/simple

1.3 特点

Scrapy使用了Twisted异步网络框架,可以加快我们的下载速度。

异步:调用在发出之后,这个调⽤就直接返回,不管有无结果
非阻塞:关注的是程序在等待调用结果时的状态,指在不能立刻得到结果之前,该调用不会阻塞当前线程
举个例子:
同步的过程:蓝色的func1运行完毕和返回结果;黄色的func1才能进行运行和返回
异步的过程:不需要等待蓝色的func1运行完毕和返回结果才运行黄色的func1,可以同时运行蓝色的func1和黄色的func1
在这里插入图片描述

2. Scrapy的工作流程

前面我们讲了单线程和多线程的爬虫方式,我们先来回顾这两种方式的工作流程。

  • 第一种:单线程
    第一步:确定目标urls
    第二步:请求-响应目标urls
    第三步:提取目标url内的目标数据目标内容
    第四步:保存目标数据目标内容
    在这里插入图片描述
  • 第二种:多线程(生产者-消费者模式)
    类似于单线程,效率更高
    第一步:确定目标urls,存储至队列
    第二步:队列取得,多次同步请求-响应目标urls
    第三步:提取目标url内的目标数据目标内容,保存至队列
    第四步:队列取得,多次保存目标数据目标内容
    在这里插入图片描述
  • 第三种:Scrapy工作流程
    特点是:分模块进行,各司其职。先了解各个模块的功能:
    在这里插入图片描述
    Scrapy engine(引擎) :总指挥,负责数据和信号在不同模块进行传递。(不需要撰写代码,scrapy已经实现
    Scheduler(调度器) :一个队列,存放引擎发过来的request请求。(不需要撰写代码,scrapy已经实现
    Downloader(下载器) :下载引擎发过来的request请求,并返回给引擎。(不需要撰写代码,scrapy已经实现
    Spider(爬虫) :处理引擎发来的response,提取数据,提取url,并交给引擎。(需要手写
    Item Pipline(管道) :处理引擎传过来的数据,比如存储。(需要手写
    Downloader Middlewares(下载中间件) :可以自定义下载拓展,如代理(user-agent)。(一般不用手写
    Spider Middlewares(下载中间件) :可以自定义request请求和进行response过滤。(一般不用手写

再具体举个例子,串整个流程:
首先,调度器(Scheduler)存放着目标urls或者是存放引擎发过来的request请求。
然后,引擎(Scrapy engine)协调调度器(Scheduler)把请求发给下载器(Downloader),让下载器下载请求,并返回给引擎。
接着,引擎(Scrapy engine)把获得的响应发给爬虫(Spider),爬虫处理引擎发来的response,提取数据,提取url,并交给引擎‘
最后,引擎(Scrapy engine)把响应内容发给管道(Item Pipline),管道处理引擎传过来的数据,比如存储。
也就说,Scrapy还是类似于队列模式(多线程),但是它把每个任务分在了每个模块,让每个模块各司其职,最后耦合一起。

3. Scrapy基本结构

  • 1 创建⼀个 scrapy 项⽬
scrapy startproject mySpider

创建成功
在这里插入图片描述
在这里插入图片描述

  • 2 定义提取的Item
    在这里插入图片描述
    Item 是保存爬取到的数据的容器;其使用方法和python字典类似。虽然您也可以在Scrapy中直接使用dict,但是 Item 提供了额外保护机制来避免拼写错误导致的未定义字段错误

  • 3 编写爬取网站的 spider 并提取 Item
    语法:

scrapy genspider demo "demo.cn"

举例:爬取豆瓣-创建一个豆瓣爬虫py
在这里插入图片描述
在这里插入图片描述
name: 用于区别Spider。 该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。
start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象

  • 4.编写 Item Pipeline 来存储提取到的Item(即数据)
    在这里插入图片描述
  • 5.此外 setting 和middlewares
    setting是设置一些爬取的设置,如代理头,响应范围等
    middlewares是中间件
    不需要多修改,我们主要要在创建的py文件和pipline的py文件中撰写

在这里插入图片描述
在这里插入图片描述

4. Scrapy爬虫入门

4.1 查看访问响应

  1. 编写爬取网站的 spider - db文件,查看响应情况
# -*- coding: utf-8 -*-
import scrapy


class DbSpider(scrapy.Spider):  # 类名不改
    name = 'db'
    allowed_domains = ['douban.com']  #  爬取范围  可以修改
    start_urls = ['http://douban.com/']  # 从 此url开始  可以修改

    def parse(self, response):   # 解析的方法,方法名不改
        print('='*40)
        print(response)  # 响应情况
        print(type(response))
        print('=' * 40)
  1. 修改setting文件
    补充User-agent、修改响应范围、简化输出内容
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 运行代码

有两种方式
第一种:
终端运行爬虫代码:

scrapy crawl db # db 爬⾍的名字

第二种:
在pycharm中运行爬虫

from scrapy import cmdline
cmdline.execute("scrapy crawl qb".split())

采用终端运行
在这里插入图片描述
在这里插入图片描述

4.2 爬取网页内容

爬取豆瓣网页便签关键词,如
在这里插入图片描述
爬虫的db文件代码

# -*- coding: utf-8 -*-
import scrapy
from scrapy.http.response.html import HtmlResponse
from scrapy.selector.unified import SelectorList

class DbSpider(scrapy.Spider):  # 类名不改
    name = 'db'
    allowed_domains = ['douban.com']  #  爬取范围  可以修改
    start_urls = ['http://douban.com/']  # 从 此url开始  可以修改

    def parse(self, response):   # 解析的方法,方法名不改
        # 获取响应码
        # print('='*40)
        # print(response)
        # print(type(response))
        # print('=' * 40)

        # 获取网页内容
        li_list = response.xpath("//div[@class='side-links nav-anon']/ul/li")  # 利用xpath方式 获取标签内容
        # 定义一个字典 保存数据
        # 从xpath中获取的selector对象,selector对象是所有代码都爬取,因而之后我们要提取数据内容
        # 我们有2种方式   例如数据: <a>这是一个文字</a>
        # 1.get() / getall() 得到所有代码--> <a>这是一个文字</a>
        # 2.extract_first() 得到文字 --> 这是一个文字
        item = {}
        for li in li_list:
            item['name'] = li.xpath('a/text()').extract_first()
            print(item)

通过py文件运行爬虫项目得到数据
在这里插入图片描述

4.3 保存网页内容

  1. 爬虫项目dbreturn数据给管道
# -*- coding: utf-8 -*-
import scrapy
from scrapy.http.response.html import HtmlResponse
from scrapy.selector.unified import SelectorList

class DbSpider(scrapy.Spider):  # 类名不改
    name = 'db'
    allowed_domains = ['douban.com']  #  爬取范围  可以修改
    start_urls = ['http://douban.com/']  # 从 此url开始  可以修改

    def parse(self, response):   # 解析的方法,方法名不改
        li_list = response.xpath("//div[@class='side-links nav-anon']/ul/li")  
        item = {}
        for li in li_list:
            item['name'] = li.xpath('a/text()').extract_first()
            yield item  # return  给 管道 pipeline 保存数据

# 在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前运行的信息,返回yield的值。并在下一次调用next()函数时从当前位置继续运行
  1. 在setting中打开打开管道设置
    在这里插入图片描述
    介绍:从pipeline的字典形可以看出来,pipeline可以有多个,而且确实pipeline能够定义多个,需要多个pipeline的原因:
    1 可能会有多个spider,不同的pipeline处理不同的item的内容
    2 ⼀个spider的内容可以要做不同的操作,比如存入不同的数据库中
    注意:
    1)pipeline的权重越小,优先级越高。图片中设置的pipeline优先级设置为300,若再设置一个pipeline1优先级数为400,则pipeline先于pipeline1执行
    2) pipeline中process_item方法名不能修改为其他的名称

  2. pipline 管道 保存数据

代码

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


import json

class MyspiderPipeline:   #  设置管道,设置多个管道,则根据管道优先级进行
    def __init__(self):
        self.f = open('demo.json','w',encoding='utf-8')
        
    # 爬虫开始的方法
    def open_spider(self,item):
        print('爬虫开始了')

    def process_item(self, item, spider):
        print(item)
        # json.dumps() 可以将自定形式的数据转换为字符串
        # ensure_ascii=False 在转换的时候默认的是ascii字符
        item_json = json.dumps(item,ensure_ascii=False)
        self.f.write(item_json+'\n')
        return item
    # p爬虫结束的方法
    def close_spider(self,item):
        print('爬虫结束了')
        self.f.close()

运行结果:
在这里插入图片描述
得到json文件
在这里插入图片描述

4.4 多个爬虫文件在同一个项目

首先,在同一个scrapy建立多个爬虫文件,如建一个demo.py文件:
在这里插入图片描述
现在有两个爬虫文件,如何选择爬取哪一个?
第一种方式:根据pipline文件里的spider.name 来定义

import json

class MyspiderPipeline:
    def __init__(self):
        self.f = open('demo.json','w',encoding='utf-8')

    # 爬虫开始的方法
    def open_spider(self,item):
        print('爬虫开始了')

    def process_item(self, item, spider):
        if spider.name == "db":
            print(item)
            item_json = json.dumps(item,ensure_ascii=False)
            self.f.write(item_json+'\n')
            return item
        elif spider.name == "demo":
            print(spider.name)
    # p爬虫结束的方法
    def close_spider(self,item):
        print('爬虫结束了')
        self.f.close()

第二种方法:根据pipline文件里的item项目来判定

class MyspiderPipeline:
    def __init__(self):
        self.f = open('demo.json','w',encoding='utf-8')

    # 爬虫开始的方法
    def open_spider(self,item):
        print('爬虫开始了')

    def process_item(self, item, spider):
        # 在db文件的item项目添加come_from key
        if item['come_from'] == "db":
            print(item)
            item_json = json.dumps(item,ensure_ascii=False)
            self.f.write(item_json+'\n')
            return item
        # 在demo文件的item项目添加come_from key
        elif item['come_from'] == "demo":
            print(spider.name)
    # p爬虫结束的方法
    def close_spider(self,item):
        print('爬虫结束了')
        self.f.close()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值