scrapy框架

本文详细介绍了Scrapy框架的用途、安装步骤、基础指令、工程目录结构、数据解析方法及持久化存储策略,包括基于终端指令和管道的存储方式,并提供了实际操作示例。在持久化存储部分,讨论了如何将数据保存到本地、MySQL和Redis。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

scrapy

简介

scrapy是一个专门用于异步爬虫的框架,框架可以理解为是一个被集成了很多功能且具有很强通用性的一个项目模板。

安装

1 终端输入

pip install scrapy

2 anaconda - environments - base(root) -search packages搜索scrapy下载,回到pycharm中import后直接下载,或是在preference-project interpreter 按+ 搜索后 install package

下载显示成功后在终端输入scrapy,没报错就说明下载成功

基础使用指令

  • 创建
scrapy startproject ProName
scrapy startproject onePick
  • 进入工程
cd ProName
cd onePick
  • 创建爬虫源文件,网址可以创建后修改
    • 在spider中创建爬虫文件,一般情况下只创建1个,name对应的属性值就是该爬虫文件,它是当前源文件的唯一标识
    • 如果在spider中创建多个爬虫文件,name对应的属性值不可相同
scrapy genspider spiderName www.xxx.com
scrapy genspider one www.xxx.com
  • 执行工程
    • 在pycharm中只能使用指令执行,无法通过run 执行
    • 不能同时执行多个爬虫文件,只能是一条指令执行一个
    • 直接进行执行工程后,默认会输出工程的日志信息
scrapy crawl spiderName
scrapy crawl one
  • 在创建爬虫源文件后,可先到settings.py中进行修改:
    • 写入LOG_LEVEL = 'ERROR'
    • 找到ROBOTSTXT_OBEY = True并修改为ROBOTSTXT_OBEY = False
    • 找到UA并写入

在这里插入图片描述

工程下的目录结构

在这里插入图片描述

  • duanziPro(ProName) :创建工程后会生成一个工程同名的文件夹
  • spider :爬虫文件夹,该文件夹必须要存放一个爬虫源文件
  • items.py :可以理解为一种容器,存储爬取的数据
  • pipelines.py :管道类
  • settings.py :工程的配置文件
  • scrapy.cfg:配置文件

数据解析

  • 测试流程

打开终端,进入指定文件夹内 cd 3\ scrapy
创建工程scrapy startproject onePick
进入工程cd onePick
创建爬虫文件scrapy genspider theOne www.xxx.com
打开settings.py,做3步修改
打开theOne.py

import scrapy

# TheoneSpider 文件名+spider作方法名,Spider是它的父类
class TheoneSpider(scrapy.Spider):
    # 爬虫文件的名称:当前源文件的唯一标识
    name = 'theOne'
    # 允许的域名(通常不用)
    # 限定请求发送的URL,如在allowed_domains中指定了单独的域名,无论start_urls中有多少个域名都只能访问属于指定域名之下的URL
    # allowed_domains = ['www.xxx.com']
    # 起始URL列表:只可以存储URL
    # 作用:列表中储存的URL都会被进行get请求的发送,如需要post要重写父类方法
    start_urls = ['https://www.baidu.com/','https://www.sougou.com']

    # 数据解析
    # parse方法调用的次数取决于请求发送的次数(start_urls列表里的URL请求次数)
    # response:表示的是服务器返回的响应对象
    def parse(self, response):
		print(response)

执行工程scrapy crawl theOne


  • scrapy数据解析

使用response.xpath(‘xpath表达式’)
scrapy封装的xpath和etree中的xpath区别:
scrapy中的xpath直接将定位到的标签中存储的值或者属性值取出,返回的是Selector对象,且相关的数据值是存储在Selector对象的data属性中,需要调用extract、extract_first()取出字符串数据

import scrapy
class DuanziSpider(scrapy.Spider):
    name = 'duanzi'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['http://www.duanziku.com/gaoxiaoduanzi/']
# 数据解析
    def parse(self, response):
        paper_list = response.xpath('/html/body/div[5]/div[1]/ul')
        for paper in paper_list:
            # 返回Selector对象,数据存储在对象的data属性中
            title = paper.xpath('./li/h3/a/text()')[0]
            content = paper.xpath('./li/p[2]/text()')[0]

            # .extract() 从Selector对象中取出data属性值,返回字符串
            title = paper.xpath('./li/h3/a/text()')[0].extract()
            content = paper.xpath('./li/p[2]/text()')[0].extract()

            # 直接使用列表调用extract() 可以将列表中的每一个列表元素表示的Selector中data取出,返回列表
            title = paper.xpath('./li/h3/a/text()').extract()
            content = paper.xpath('./li/p[2]/text()').extract()

            # .extract_first() 将列表中的第一个列表元素表示的Selector对象中的data值取出
            title = paper.xpath('./li/h3/a/text()').extract_first()
            content = paper.xpath('./li/p[2]/text()').extract_first()
            print(title,content)
            break

直接调用xpath表达式,返回的不是字符串,是Selector对象,所需的文本数据存储在selector对象中的data属性中
在这里插入图片描述

 <Selector xpath='./li/h3/a/text()' data='少小离家老大回,安能辨我是雌雄'> <Selector xpath='./li/p[2]/text()' data='1.大学时不喜欢读书,跟上铺的哥们说,我最羡慕那些徒步旅行的驴友,想去那里...'>

在这里插入图片描述

 [0].extract():少小离家老大回,安能辨我是雌雄 1.大学时不喜欢读书,跟上铺的哥们说,我最羡慕那些徒步旅行的驴友,想去那里就去那,真想来一次说走就走的徒步旅行,只可惜……
 .extract():['少小离家老大回,安能辨我是雌雄', '据说女人很喜欢这个笑话', '小明,你出去!(四)', ‘搞笑段子:……俺老孙来也! 老夫子也想凑个...']
 extract_first():少小离家老大回,安能辨我是雌雄 1.大学时不喜欢读书,跟上铺的哥们说,我最羡慕那些徒步旅行的驴友,想去那里就去那,真想来一次说走就走的徒步旅行,只可惜……

持久化储存

基于终端指令的持久化储存

执行指令:scrapy crawl spiderName -o filePath
该种方式只可以将parse方法的返回值存储到本地指定后缀的文本文件中

scrapy crawl duanzi -o duanzi.txt
error: Unrecognized output format 'txt'. Set a supported one (('json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle')) after a colon at the end of the output URI (i.e. -o/-O <URI>:<FORMAT>) or as a file extension.

实操

import scrapy

class DuanziSpider(scrapy.Spider):
    name = 'duanzi'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['http://www.duanziku.com/gaoxiaoduanzi/']

	# 持久化存储
    def parse(self, response):
        all_data = []
        paper_list = response.xpath('/html/body/div[5]/div[1]/ul')
        for i in range(1,10):
            page = str(i)
            for paper in paper_list:

                # 数据解析title和content
                title = paper.xpath('./li'+ '[' + page +']' +'/h3/a/text()').extract_first()
                content = paper.xpath('./li'+'[' + page +']'+'/p[2]/text()').extract_first()


                dic = {
                    'title' : title,
                    'content' : content
                }
                all_data.append(dic)

        return all_data

执行指令scrapy crawl duanzi -o duanzi.csv
在这里插入图片描述

基于管道的持久化储存
步骤
  • 在爬虫文件中进行数据解析(发送请求,xpath表达式定位获取数据)
    在这里插入图片描述
  • items.py中定义相关属性(在爬虫文件中解析了几个字段的数据,在此就定义几个属性)
    在这里插入图片描述
  • 在爬虫文件中将解析到的数据存储封装到Item类型的对象中 将Item类型的对象提交给管道
    • 不可以通过.xxx的方式调用属性,item中存储的是键值对
      在这里插入图片描述
  • 在管道文件pipelines.py中,接收爬虫文件提交过来的Item类型对象,且对其进行任意形式的持久化存储操作
    在这里插入图片描述
    在这里插入图片描述
  • 在配置文件中开启管道机制
    • ITEM_PIPELINES = {'duanziPro.pipelines.DuanziproPipeline': 300,}
    • 300表示管道类的优先级,数值越小优先级越高,优先级高的管道类先被执行
      在这里插入图片描述
完整代码
  • 爬虫文件
import scrapy
from duanziPro.items import DuanziproItem

class DuanziSpider(scrapy.Spider):
    name = 'duanzi'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['http://www.duanziku.com/gaoxiaoduanzi/']

	# 基于管道的持久化存储
    def parse(self, response):
        all_data = []
        paper_list = response.xpath('/html/body/div[5]/div[1]/ul')
        for i in range(1,10):
            page = str(i)
            for paper in paper_list:

                # 数据解析title和content
                title = paper.xpath('./li'+ '[' + page +']' +'/h3/a/text()').extract_first()
                content = paper.xpath('./li'+'[' + page +']'+'/p[2]/text()').extract_first()

                # 实例化一个item对象,将解析到的数据存储到该对象中
                item = DuanziproItem()
                # tips: 不可以通过.xxx的方式调用属性,item中存储的是键值对
                item['title'] = title
                item['content'] = content

                # 将item对象提交给管道
                yield item
  • items.py
import scrapy


class DuanziproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # Field() 定义好的属性当做是一个万能类型的属性
    # 在爬虫文件中解析了几个字段的数据,在此就定义几个属性
    title = scrapy.Field()
    content = scrapy.Field()
  • 管道文件pipelines.py
from itemadapter import ItemAdapter

class DuanziproPipeline(object):
    fp = None
    # 重写父类方法
    def open_spider(self,spider):
        print('open_spider(),爬虫开始前执行1次')
        self.fp = open('duanzi.txt','w',encoding='utf-8')

    def close_spider(self,spider):
        print('close_spider(),爬虫结束后执行1次')
        self.fp.close()

    def process_item(self, item, spider):
        # item是爬虫文件提交过来 接收到的item对象,item其实是一个字典,存储键值对
        self.fp.write(item['title']+':'+item['content']+'\n')
        # 将item存储到文本文件中
        return item
  • settings.py
ITEM_PIPELINES = {
   'duanziPro.pipelines.DuanziproPipeline': 300,
}

实现备份(存储在本地、MySQL、Redis)

一个管道类对应一种形式的持久化存储操作,如果将数据存储到不同的载体中就需要使用多个管道类。定义后将数据写入,item不会依次提交给多个管道类,只会被提交给优先级最高的管道类,优先级高的管道类需要在process_item中实现return item,使得优先级低的管道类能够接收到并执行,直到最后一个被执行的管道类,不再需要return item

之前通过Java学的MySQL,还没学过Redis,这部分待学习后再做调整

  • 爬虫文件(同上不变)
  • items.py (同上不变)
  • settings.py
ITEM_PIPELINES = {
  # 300表示管道类的优先级,数值越小优先级越高
  # 优先级高的管道类先被执行
  'duanziPro.pipelines.DuanziproPipeline': 300,
  'duanziPro.pipelines.MysqlPipeline': 301,
  'duanziPro.pipelines.RedisPipeline': 302,
}
  • 管道文件pipelines.py
from itemadapter import ItemAdapter
import pymysql
from redis import Redis

class DuanziproPipeline(object):
    fp = None
    # 重写父类方法
    def open_spider(self,spider):
        print('open_spider(),爬虫开始前执行1次')
        self.fp = open('duanzi.txt','w',encoding='utf-8')

    def close_spider(self,spider):
        print('close_spider(),爬虫结束后执行1次')
        self.fp.close()

    def process_item(self, item, spider):
        # item是爬虫文件提交过来 接收到的item对象,item其实是一个字典,存储键值对
        self.fp.write(item['title']+':'+item['content']+'\n')
        # 将item存储到文本文件中
        return item


class MysqlPipeline(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='utf-8')
        print(self.conn)


    def process_item(self, item, spider):

        self.cursor = self.conn.cursor()
        sql = 'insert into duanzi values ("%s","%s")'%(item['title'],item['content'])

        # 开启事务
        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()


class RedisPipeline(object):
    conn = None

    # 重写父类方法
    def open_spider(self, spider):
        self.conn = Redis(host='127.0.0.1',port=6379)
        print(self.conn)

    def process_item(self, item, spider):

        self.conn.lpush('duanziData',item)

        # return item   优先级最低,不用再传给下一个管道类
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值