Scrapy框架

一.什么是Scrapy?
        Scrapy是一个为 了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍。所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)的具有很强通用性的项目模板。对于框架的学习,重点是要学习其框架的特性、各个功能的用法即可。

 

        - 组件的作用:
                ● 引擎(Scrapy)
                        作用:判读数据对象,触发下一次步骤。用来处理整个系统的数据流处理,触发事务(框架核心)
                ● 调度器(Scheduler)
                        作用:只会接收spider对象生成的请求对象。用来接受引擎发过来的请求,压入队列中,并在引擎再次请求的时候返回.可以想像成-个URL (抓取网页的网址或者说是链接)的优先队列, 由它来决定下一-个要抓取的网址是什么,同时去除重复的网址
                ● 下载器( Downloader)
                        作用:从互联网中请求数据。用于下载网页内容,井将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
                ● ​​​​​​​爬虫(Spiders)
                        作用:1.批量产生URL。2.用于数据解析。爬虫是主要干活的,用于从特定的网页中提取自2需要的信息,即所谓的实体(tem)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
                ● 项目管道(Pipeline)
                        作用:持久化存储负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。管道就是将一个程序的输出重定向为另一个程序的输入。
        - 请求传参实现的深度爬取
                - 深度爬取:爬取的数据没有在同一张页面中(首页数据+详情页数据)
                - 在scrapy中如果没有请求传参我们是无法持久化存储数据
                - 实现方式:
                        scrapy . Request(url, callback , meta)
                                meta是一个字典, 可以将meta传 递给callback
                        callback取出meta:
                                response. meta 


 

        - 中间件:
                作用:批量拦截请求和响应
                爬虫中间件
                下载中间件(推荐)
                        - 拦截请求:
                                篡改请求url
                                伪装请求头信息
                                        UA
                                        Cookie
                                设置请求代理(重点)
                         - 拦截响应
                                篡改响应数据
        - 代理操作必须使用中间件才可以实现
                process_ exception:
                        request .meta['proxy'] = 'http://ip:port'

二.安装
        Linux:
                pip3 install scrapy
        Windows:
                a. pip3 install wheel
                b.下载twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
                c.进入下载目录,执行pip3 install Twisted-20.3.0-cp37-cp37m-win_amd64.whl
                        注意:必须保证安装成功。安装失败,可以换另一个版本的twisted文件再次进行安装
                d. pip3 install pywin32 
                e. pip3 install scrapy

三.基本使用
        - 创建一个工程
                scrapy startproject proName
                - 工程目录下的两个文件表示的含义:
                        - spiders包:爬虫文件夹
                                必须在爬虫文件夹中创建一个爬虫源文件
                        - settings.py:配置文件
        - cd proName 
        - 创建一个爬虫文件(爬虫文件要创建在spiders包中)
                - scrapy genspider spiderName www xxx.com                                                                                  - 该指令可以创建多个爬虫文件,但是爬虫文件名称不可以重复                                                - 编写爬虫文件
        - 执行工程
                - scrapy crawl spiderName

import scrapy

class FirstSpider(scrapy.Spider):
    # name表示爬忠文件的名称,爬虫文件的名称表示的是爬虫文件的唯一标识
    name = 'first'
    #允许的域名:用来做请求限定。一旦该域名定义好之后。则start url只可以发起该域名下的url的get请求
    allowed_domains = ['www.xxx.com']
    #起始的url列表:将想要爬取的urlm存放在该列表中,这个列表就可以帮我们将每一个ur1进行get请求的发送
    start_urls = ['http://www.xxx.com/']

    #用作于数据解析。response参数就是请求回来的响应对象
    def parse(self, response):
        print(response)
        pass

四.爬虫文件的编写
        定义好了一个类,该类的父类是Spider, Spider是sC rapy所有类的父类
        -类中定义好了三个属性和一个方法
                - name :
                        爬虫文件的名称
                - start_ urls:起始url列表
                        作用:可以对列表中的ur1进行get请求的发送
                - allow_ demains :允许的域名。
                - parse(self, response ) :
                        将起始ur1列表中的url请求成功后,response就是获取的响应对象,在该方法中负责实现数据解析
        scrapy工程默认是遵从rotbos协议的,需要在配置文件中进行操作:
                不遵从robots协议    False
        指定日志等级
                - LOG_LEVEL = ' ERROR '

# 数据解析
    def parse(self, response):
        # respanse. expathO
        # tree.expathl
        # 上述两个xpath不是同一个方法,但是使用上基本一致。只有细微的差异
        li_list = response.xpath(' //* [@id="list"]/ul/li')
        for li in li_list:
            # 返回的不是宇符串,而是一个Selector对象.且提取的字符串数据被存储在了该对象中
            content = li.xpath('./div[1]/text()')[0].extract()
            # title = li. xpath('./div [2]/span//text()' )#返回的是列表,列表中有多个元素
            # title = join(title)  # 将列表转成字符串
            print('内容:', content)
            # print('标题:', title)
            break

五. 数据解析
        - response. xpath()
        - 注意:提取标签内容时,返回的不是字符串,而是Selector对象, 字符串是存储在该对象中的。需要调用extract( )或者extract_ first( )将Selector对象中的字符串取出。
六. 持久化存储
        - 基于终端指令:
        - 只可以将parse方法的返回值存储写入到指定后缀的文本文件中。通过指定方式执行工程:
                - scrapy crawl duanzi -o data_duanzi. csv
        - 基于管道:
                - 实现流程:
                        - 1.在爬虫文件中解析数据
                        - 2.在Item类中定义相关的属性(解析的数据有几个字段就定义几个属性)
                        - 3.将在爬虫文件中解析的数据存储封装到Item对象中
                        - 4.将存储了解析数据的Item对象提交给管道
                        - 5.在管道文件中接受Item对象,且对其进行任意形式的持久化存储操作
                        - 6.在配置文件中开启管道

并基于管道的持久化存储
    def parse(seLf, response):
        li_list = response.xpath('//* [@id="list"]/ul/li')
        for li in li_ list:
            content = li. xpath( './div[1]/text()').extract_ first()
            title = li. xpath( './div [2]/span//text()').extract()#返回的是列表列表中有多个
            title = ''.join(title)#将列表转成宇符串
            #将解析到的数据存储到Item对象
            item = DuanziproItem( ) 
            #注意: itemL'title' 1访问item对象中的title属性(只可以这样访问属性)
            item['title'] = title
            item ['content'] = content
            #将item对象提交给管道(pipelines.py)
            yield item

        - 如何实现数据的备份
                - 指的是将爬取到的一组数据存储到多个不同的载体(文件, mysql, redis) 中。
                - 持久化存储的操作必须要写在管道文件中
                        - 一个管道类对应一种形式的持久化存储
                                - 如果想将数据存储到多个载体中则必须要有多个管道类
                - 问题:让两个管道类都接受到item且对其进行持久化存储,爬虫文件提交的item可同时提交给两个管道类?
                        - 爬虫文件提交的item只可以提交个优先级最高的那一个管道类。

                - 如何可以让优先级低的管道类也可以获取接受到item呢?
                        - 可以让优先级高的管道类在process_ item中通过return item的形式将item传递给下一个即将被执行的管道类。

管道文件的编写

#该管道类是将数据在储到了本地文件

class FirstbloodPipeline:
    fp = None
    #重写父类一个方法:只会在爬虫开始后被执行一次
    def open spider(self,spider):
        print('i am open_ spider()' )
        fp = open('./duanzi.txt', 'w', encoding='utf-8')
        #这个方法是用来接收爬虫文件提交过来的item对象(一 次只能接受个item对象)共参数item:就是接受到item对象
    def process_ item(self, item, spider):
        #将接收到的item对象写入文件
        title = item['title'], #将item对象中存储的值取出
        content = item['content']
        #open('text.txt' )#写在此处不合适。因为process_item方法会被调用多次
        return item

管道文件储存到MySQL中

import pymysql

#将数据存储到mysa1中一份
class MysqlPileline(object):
    conn = None
    cursor = None
    def open_spider(self, spider):
        self.conn = pymysql.Connect(host='127.0.0.1',port=3306, user='root',password='123456',db='spider',charset='utf8') 
        print(self.conn)
    def process_item(self, item, spider): 
        title = item['title']
        content = item['content']
        sql = 'insert into duanzi values ("%s", "%s")'%(title,content)
        #使用游标对象执行sql语句
        self.cursor = self.conn.cursor()
        try:
            self.cursor.execute(sql)
            self.conn.commit()
        except Exception as e:
            print(e)
            self.conn.rollback()
        return item
    def close_spider(self, spider):
        self.cursor.close()
        self.conn.close()

 七.手动请求发送实现的全站数据爬取
        - 如何通过代码手动对指定的url进行请求发送
                - yield scrapy.Request(url, callback) :get请求
        - 如何手动发起post请求
                - yield scrapy.FormRequest(url, formdata, callback) post请求
                formdate:字典,请求参数。注意:在scrapy中一般不发送post请求                            为什么start_ urls列表中的url会被自动进行get请求的发送?
        - 因为列表中的ur1其实是被start_ requests这个父类方法实现的get请求发送
                def start_ requests(self):
                        for u in self.start_urls:
                                yield scrapy . Request (url=u, callback=self. parse)
   如何将start_ _urls中的urL默认进行post请求的发送?
        - 重写start_ requests方法即可
                def start_ requests(self):
                        for u in self.start_urls:
                                yield scrapy.FormRequest(url=u, callback=self.parse,fromdata=data)

  

#手动请求发送的操作
if self.page <= 120 :进结束递归的条件
    #手动请求发送的操作
    new_url = format(self.url, self.page)
    self.page += 30
    #callback参数:请求成功会调用指定的回调函数进行数据解析
    yield scrapy.Request(urL=new_url, callback=self.parse)扶手动对指定的url进行get请求

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值