scrapy settings和管道的深入

scrapy深入认识settings.py文件

为什么在我们的scrapy项目中需要有一个settings.py文件呢?

  • 配置文件存放一些公共的变量(比如数据库的地址、账号+密码等),方便自己和别人修改
  • 一般使用全大写字母命名变量名,例如LOG_LEVEL="WARN"

settings.py文件重要代码的解读

BOT_NAME = 'Sun'  # 项目名

SPIDER_MODULES = ['Sun.spiders']  # 爬虫的位置
NEWSPIDER_MODULE = 'Sun.spiders'  # 如果我们新建一个爬虫,这个新建爬虫的位置

LOG_LEVEL="WARN"  # log日志显示的最低等级,只有等级大于或等于LOG_LEVEL的才会在终端中显示

# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36"
# 浏览器的身份标识,即是"User-Agent"

# Obey robots.txt rules
ROBOTSTXT_OBEY = True
# 默认情况下为True,表示遵守这个网站的robots协议
# 如果我们设置
# ROBOTSTXT_OBEY = True  # 不遵守robots协议
# 遵守robots协议的体现:最开始请求url地址的时候会先请求对应的robots.txt,如果我们不遵守robots协议,就不会请求

# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32  # 设置最大并发请求
# scrapy中封装了一个twisted异步网络框架,在发送网络请求的时候不会说等一个请求请求成功之后再去发送下一个请求,而是同时去发送很多个请求
# 大概有多少个请求可以同时被发送呢?我们可以在这里自定义数量
# 注意:默认是16个,我们可以根据自己的爬虫项目需要自定义CONCURRENT_REQUESTS的数量
# CONCURRENT_REQUESTS的值越大,爬虫爬取的速度越快
# 但是注意,CONCURRENT_REQUESTS的值越大,越有可能被对方的服务器识别为一个爬虫程序
# 所以说,要适当设置CONCURRENT_REQUESTS的数量

#DOWNLOAD_DELAY = 3  # 下载延迟
# 每次请求之前,休眠3秒
# 可以让我们的爬虫请求速度变慢一些
# The download delay setting will honor only one of:
# 就是说我们的DOWNLOAD_DELAY参数可以配合着下面的CONCURRENT_REQUESTS_PER_DOMAIN参数和CONCURRENT_REQUESTS_PER_IP参数来使用
#CONCURRENT_REQUESTS_PER_DOMAIN = 16  # 每一个域名的最大并发请求数目
#CONCURRENT_REQUESTS_PER_IP = 16  # 每一个IP的最大并发请求数目

# Disable cookies (enabled by default)
#COOKIES_ENABLED = False  # cookie是否开启
# 默认情况下是开启的,也就是说我们请求完一个url地址之后,去请求下一个url地址的时候,scrapy默认是带上前一次请求对方服务器设置在我们本地的cookie信息
# 很重要

# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False
# 这是我们scrapy框架的一个插件
# 默认是开启的状态

# Override the default request headers:
#DEFAULT_REQUEST_HEADERS = {
#   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
#   'Accept-Language': 'en',
#}
# 默认的请求头,默认是关闭的状态
# 开启之后,scrapy就会用这个请求头去发送请求
# 注意:如果我们将"User-Agent"参数放在这里,是没有任何效果的,因为专门有一个参数接收"User-Agent"对应的值

# Enable or disable spider middlewares
# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
# SPIDER_MIDDLEWARES = {
#    'Sun.middlewares.SunSpiderMiddleware': 543,
# }
# 爬虫中间件

# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
#    'Sun.middlewares.SunDownloaderMiddleware': 543,
#}
# 下载中间件

# Enable or disable extensions
# See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
#    'scrapy.extensions.telnet.TelnetConsole': None,
#}
# 插件

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   'Sun.pipelines.SunPipeline': 300,
}
# 管道

# 爬虫中间件、下载中间件、插件、管道的使用方法:
# 类似于ITEM_PIPELINES管道的使用方法
# 开启之后,键--位置,值--和引擎之间的距离(注意:值越大,权重越低;值越小,权重越高)

# Enable and configure the AutoThrottle extension (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
# AUTOTHROTTLE--自动限速
# 比如说我们通过scrapy爬取对方的网站,可能会由于我们的scrapy爬虫速度太快导致把对方的网站“抓崩了”
# “抓崩了”并不是我们想要的结果,因为“抓崩了”之后我们就没有办法再在对方的网站上爬取数据了
# 我们可以根据对方网站的情况让我们的scrapy爬虫速度变慢一些
# 通过调节下面的参数我们可以达到这个自动限速的目的
# 但是往往我们是不需要这样操作的
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False

# Enable and configure HTTP caching (disabled by default)
# 关于HTTP的缓存,默认是关闭的
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = 'httpcache'
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
# 如果我们想要开启HTTP缓存就可以将其打开
# 它会将我们的HTTP缓存至设置的位置,实现对应的功能
# 不常用

# 每一块内容都是有对应的官方文档的

如何在代码中使用我们在settings.py文件中所做的设置

现在,我们在settings.py文件中做了一些设置
在这里插入图片描述
settings.py文件中有一个MONGO_HOST,我们应该如何在spider中使用呢?

第一种方法:导入

1.导入
在这里插入图片描述
2.现在我们就可以使用我们在settings.py文件中定义的这个MONGO_HOST参数了
3.如果我们想要在其他文件中使用MONGO_HOST这个参数也是一样方法:导入
pipelines.py为例,
from .settings import MONGO_HOST
在这里插入图片描述

第二种方法:属性

其实我们的spider本身就有一个属性就是settings

1.如何在爬虫中使用settings属性

在这里插入图片描述

# -*- coding: utf-8 -*-
import scrapy
from ..items import SunItem
# from ..settings import MONGO_HOST

class SunSpider(scrapy.Spider):
    name = 'sun'
    allowed_domains = ['sun0769.com']
    start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1']

    def parse(self, response):
        # # spider本身就有一个属性叫做settings
        # self.settings["MONGO_HOST"]  # self.settings是一个字典
        # self.settings.get("MONGO_HOST","指定的MONGO_HOST的值")
        """
        由于self.settings是一个字典。所以我们可以对其使用
        self.settings.get("MONGO_HOST")  # 如果MONGO_HOST不存在,返回的就是一个None值
        # 或者是返回我们在get方法中给MONGO_HOST手动指定的值
        self.settings.get("MONGO_HOST","指定的MONGO_HOST的值")
        """


        # 分组
        li_list=response.xpath('//div[@class="width-12"]/ul[@class="title-state-ul"]//li[@class="clear"]')
        for li in li_list:
            item=SunItem()
            item["num"]=li.xpath('.//span[@class="state1"]/text()').extract_first()
            item["title"]=li.xpath('.//span[@class="state3"]/a[1]/text()').extract_first()
            item["response_time"]=li.xpath('.//span[@class="state4"]/text()').extract_first().strip()
            item["response_time"]=item["response_time"].split(":")[-1]
            item["ask_time"]=li.xpath('.//span[@class="state5 "]/text()').extract_first()
            item["detail_url"]="http://wz.sun0769.com"+li.xpath('.//span[@class="state3"]/a[1]/@href').extract_first()

            yield scrapy.Request(item["detail_url"],
                                 callback=self.parse_detail_url,
                                 meta={"item":item}  # 通过meta传递数据
                                 )

        # 实现翻页操作
        for page in range(2, 4):
            next_url = f"http://wz.sun0769.com/political/index/politicsNewest?id=1&page={page}"
            yield scrapy.Request(next_url,
                                 callback=self.parse
                                 )

    def parse_detail_url(self,response):
        """处理详情页的数据"""
        item=response.meta["item"]  # 取出数据

        # 注意:这样获得的内容是混杂的,包含了很多的占位符等垃圾符号
        item["content"]=response.xpath('//div[@class="details-box"]/pre/text()').extract_first()

        # 注意:图片和视频可能不止一个,也可能没有
        item["img"]=response.xpath('//div[@class="clear details-img-list Picture-img"]/img/@src').extract()
        item["video"]=response.xpath('//div[@class="vcp-player"]/video/@src').extract()

        yield item


2.如何在其他文件中使用settings属性

以pipelines.py为例
在这里插入图片描述

# -*- 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 logging
# from .settings import MONGO_HOST

logger=logging.getLogger(__name__)

class SunPipeline:
    def process_item(self, item, spider):
        # spider.settings
        # spider.settings就是self.settings
        """
        spider.settings["MONGO_HOST"]
        spider.settings.get("MONGO_HOST","指定的MONGO_HOST的值")
        """

        item["content"]=self.process_content(item["content"])
        # logger.warning(item)
        return item

    def process_content(self,content):
        """处理item中的字符串"""
        new_content=content.replace("\r\n","").replace("\xa0","")
        return new_content

scrapy深入之pipeline的使用

class JsonWriterPipeline(object):
    def open(self,spider):
        """在爬虫开启的时候执行,仅执行一次"""
        self.file=open(spider.setting.get("SAVE_FILE","./temp.json"),"w")
    
    def close(self,spider):
        """在爬虫关闭的时候执行,仅执行一次"""
        self.file.close()
    
    def process_item(self,item,spider):
        line=json.dumps(dict(item))+"\n"  # 将字典转化为json字符串
        self.file.write(line)
        return item  # 如果不return的情况下,另一个权重较低的pipeline就不会获取到该item

  • open_spider在爬虫开启的时候执行一次
  • close_spider在爬虫关闭的时候执行一次

好处1:数据库的处理:

  • 建立连接的过程就可以放在open_spider中
  • 断开连接的过程就放在close_spider中

好处2:在爬虫开始时为爬虫添加一些属性

  1. 在爬虫开始的时候为爬虫添加了一个新的属性hello,值为"world"
    位置:pipelines.SunPipeline在这里插入图片描述
    def open_spider(self,spider):
        spider.hello="world"  # 为spider创建一个新的属性叫做"hello",值为"world"
  1. 在爬虫中调用这个属性
    在这里插入图片描述
    注意:现在我们至是想要看见scrapy在爬虫启动的时候是否执行了open_spider这个方法,不需要爬取网站的信息,所以我们修改爬取的范围,即是allowed_domains

  2. 启动我们的爬虫程序

scrapy crawl sun

在这里插入图片描述
发现确实是输出了hello属性对应的值,说明我们的爬虫在开始的时候的确是调用了open_spider这个函数

pipeline中对数据库的处理

# 对数据库进行处理
from pymongo import MongoClient


class SunPipeline:
    def open_spider(self,spider):
        client=MongoClient()  # 实例化一下client
        self.collection=client["test"]["test"]

    def process_item(self, item, spider):
        # 调用self.collection,直接insert
        self.collection.insert(dict(item))

当我们需要把文件写在本地的时候

class JsonWriterPipeline(object):
    def open(self,spider):
        """在爬虫开启的时候执行,仅执行一次"""
        self.file=open(spider.setting.get("SAVE_FILE","./temp.json"),"w")
    
    def close(self,spider):
        """在爬虫关闭的时候执行,仅执行一次"""
        self.file.close()
    
    def process_item(self,item,spider):
        line=json.dumps(dict(item))+"\n"  # 将字典转化为json字符串
        self.file.write(line)
        return item  # 如果不return的情况下,另一个权重较低的pipeline就不会获取到该item

思路:

  • 在open_spider中打开一次
  • 在close_spider中关闭一次
  • 中间不停地往文件中写入数据

这种方式是可以的,但是会有问题

问题:
如果我们的爬虫在爬取网站的时候爬取到第3页的时候程序突然报错了,然后爬虫终止执行,这时候,前2页的数据能够保存在我们的文件中吗?
不会
为什么?
因为我们的文件打开之后写入数据只有在close之后数据才会写进去,如果我们不close的话,数据是不会写入的。

当我们需要把文件保存在数据库中的时候

数据库暂时还没有学,不好意思,后续补充

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值