15.scrapy框架之日志等级、请求传参、提高scrapy框架的爬取效率

一、Scrapy的日志等级

  - 在使用   scrapy crawl  爬虫文件名     运行程序时,在终端里打印输出的就是scrapy的日志信息。

  - 日志信息的种类:

        ERROR : 一般错误

        WARNING : 警告

        INFO : 一般的信息

        DEBUG : 调试信息

  - 设置日志信息指定输出:

    在settings.py配置文件中,加入

                    LOG_LEVEL = ‘指定日志信息种类’即可。

                    LOG_FILE = 'log.txt'则表示将日志信息写入到指定文件中进行存储。

    例如:

        LOG_LEVEL = ‘ERROR’      绑定日志输出,只输出error类型的日志分析,其他类型的不输出

二、请求传参

  - 在某些情况下,我们爬取的数据不在同一个页面中,例如,我们爬取一个电影网站,电影的名称,评分在一级页面,而要爬取的其他电影详情在其二级子页面中。这时我们就需要用到请求传参。

  - 案例展示:爬取http://www.55xia.com/电影网,将一级页面中的电影名称,评分一级二级页面中的导演,电影介绍进行爬取。

实现代码:

爬虫文件代码:

import scrapy
from filmPro.items import FilmproItem

class FilmSpider(scrapy.Spider):
    name = 'film'
    # allowed_domains = ['www.xxxx.com']
    start_urls = ['http://www.55xia.com/']

    def parse(self, response):
        div_list = response.xpath('//div[@class="col-xs-1-5 movie-item"]')
        for div in div_list:
            # 1.获取解析到数据,并在items文件中配置属性
            title = div.xpath('.//div[@class="meta"]/h1/a/text()').extract_first()
            grade = div.xpath('.//div[@class="meta"]/h1/em/text()').extract_first()
            if grade == None:
                grade = '0'
            # 1.获取详情页面
            detail_url = 'https:' + div.xpath('.//div[@class="meta"]/h1/a/@href').extract_first()
            print(title,grade,detail_url)

            # 2.实例化一个item类型的对象
            item = FilmproItem()
            item["title"] = title
            item["grade"] = grade

            # 3.对详情的url发送请求,通过meta参数进行Request的数据传递(请求传参)
            yield scrapy.Request(url=detail_url, callback=self.getDetailPage, meta={'item': item})

    def getDetailPage(self,response):
        # 4.通过response获取item对象
        item = response.meta["item"]
        # 5.获取详情压面解析到数据,并在items文件中配置属性
        director = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[1]/td[2]/a/text()').extract_first()
        details = response.xpath('/html/body/div[1]/div/div/div[1]/div[2]/div[2]/p/text()').extract_first()
        item["director"] = director
        item["details"] = details

        yield item

items.py文件:

import scrapy

class FilmproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field() # 获取电影的标题
    grade = scrapy.Field() # 获取电影的评分
    director = scrapy.Field() # 获取详情页面中电影的导演
    details = scrapy.Field()# 获取详情页面中电影的简介

pipelines.py管道文件

class FilmproPipeline(object):
    fp = None
    def open_spider(self,spider):
        self.fp = open('./file.txt','w',encoding='utf-8')
        print("爬虫开始了!!!")

    def process_item(self, item, spider):
        self.fp.write(item['title'] + ":" + item['grade'] + ":" + item['director'] + item['details'] + "
")
        return item

    def close_spider(self,spider):
        self.fp.close()
        print("爬虫结束了!!!")

settiung.py配置文件

# 开启管道服务
ITEM_PIPELINES = {
   'filmPro.pipelines.FilmproPipeline': 300,
}

总结:

  当使用scrapy进行数据爬取的时候,如果发现爬取的数据值没有在同一张页面中进行存储.
则必须使用请求传参进行处理(持久化存储),在scrapy框架中,使用meta()进行请求传参

三、如何提高scrapy的爬取效率
增加并发:
    默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置成了为100。

降低日志级别:
    在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL = ‘INFO’

禁止cookie:
    如果不是真的需要cookie,则在scrapy爬取数据时可以进制cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:COOKIES_ENABLED = False

禁止重试:
    对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:RETRY_ENABLED = False

减少下载超时:
    如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:DOWNLOAD_TIMEOUT = 10 超时时间为10s

 测试案例:

  爬取4k高清壁纸图片 http://pic.netbian.com/

测试代码:

 爬虫文件:

import scrapy
from imagesPro.items import ImagesproItem


class Image4kSpider(scrapy.Spider):
    name = 'image4K'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['http://www.xxx.com/']
    url = "http://pic.netbian.com/index_%d.html"
    page = 1

    def parse(self, response):
        li_list = response.xpath('//div[@class="slist"]/ul/li')
        for li in li_list:
            # 获取解析到数据值,并在items文件中设置属性
            img_url ="http://pic.netbian.com" + li.xpath('./a/span/img/@src | ./a/img/@src').extract_first()
            img_name = li.xpath('./a/span/img/@alt | ./a/img/@alt').extract_first()

            #实例化item类型的对象,并将解析到的数据值储存到item对象中
            item = ImagesproItem()
            item["img_name"] = img_name

            # 使用yield获取详情页面,通过meta参数进行Request的数据传递(请求传参)
            yield scrapy.Request(url=img_url,callback=self.img_name,meta={"item":item})

        # 爬取多个分页页面
        if self.page <10:
            self.page += 1
            new_url = format(self.url%self.page)
            yield scrapy.Request(url=new_url,callback=self.parse)

    def img_name(self,response):
        # 通过response获取item对象
        item = response.meta["item"]
        item["img_data"] = response.body

        yield item

  items.py文件

import scrapy

class ImagesproItem(scrapy.Item):
    # define the fields for your item here like:
    img_name = scrapy.Field()
    img_data = scrapy.Field()
pipelines.py(数据持久化存储)
import os
class ImagesproPipeline(object):
    def open_spider(self,spider):
        if not os.path.exists("images"):
            os.mkdir("./images")
    def process_item(self, item, spider):
        imgPath = "./images" + item["img_name"] + ".jpg"
        with open(imgPath,"wb") as fp:
            fp.write(item["img_data"])
            print(imgPath + "下载成功")
        return item

setting.py文件配置

ITEM_PIPELINES = {
   'imagesPro.pipelines.ImagesproPipeline': 300,
}
CONCURRENT_REQUESTS = 10  # 默认开启10个线程
LOG_LEVEL = "ERROR"  # 默认打印错误信息日志,如果没有则不打印
COOKIE_ENABLED = False  # 警用cookie
RETRY_ENABLED = False #禁止重试
DOWNLOAD_TIMEOUT = 10 # 设置超时时间
原文地址:https://www.cnblogs.com/mwhylj/p/10267458.html