scrapy主动退出爬虫的代码片段(python3)

Posted huangtao1927

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scrapy主动退出爬虫的代码片段(python3)相关的知识,希望对你有一定的参考价值。

问题:在运行scrapy的过程中,如果想主动退出该怎么做?

背景:比如说我只要爬取当日的新闻,那么在遍历的时候,如果出现了超过1条不是当日的新闻,那么就不爬取了,就主动退出爬虫,这个时候该怎么做呢?

IDE:pycharm

版本:python3

框架:scrapy

系统:windows10

代码如下:

# -*- coding: utf-8 -*-
import scrapy
from torrentSpider.items.NavigationItem import NavigationItem
from torrentSpider.items.TorrentItem import TorrentItem
import time
import random
import logging
import os


class XxxSpider(scrapy.Spider):
    name = "xxx_spider"
    allowed_domains = [www.xxx.com]
    start_urls = [http://www.xxx.com/1.html]

    # 网站前缀
    web_pre_url = http://xxx.com
    # 计数
    count = 0

    def parse(self, response):

        # 设置请求也随机延迟
        time.sleep(random.randint(0, 5))

        # 获取导航栏的数量
        navigation_type_number = response.xpath(//*[@id="hypoNav"]/div/ul/li/em/a/text()).extract()
        for n_k in range(1, len(navigation_type_number)):
            navigation_item = NavigationItem()
            # 网站标题
            navigation_item[navigation_title] = response.xpath(//*[@id="logoSea"]/div[1]/a/img/@alt).extract()[0]
            # 导航栏目分类名称
            navigation_item[navigation_type] = response.xpath(//*[@id="hypoNav"]/div/ul/li[+str(n_k+1)+]/em/a/text()).extract()[0]
            # 导航链接
            navigation_item[navigation_url] = response.xpath(//*[@id="hypoNav"]/div/ul/li[+str(n_k+1)+]/em/a/@href).extract()[0]

        # 获取子导航栏的数量
        sub_navigation_type_number = response.xpath(//*[@id="nodeNav"]/div/ul/li/em/a/span/text()).extract()
        for sub_k in range(1, len(sub_navigation_type_number)):
            sub_navigation_item = NavigationItem()
            # 网站标题
            sub_navigation_item[navigation_title] = response.xpath(//*[@id="logoSea"]/div[1]/a/img/@alt).extract()[0]
            # 副导航栏目分类名称
            sub_navigation_item[sub_navigation_type] = response.xpath(//*[@id="nodeNav"]/div/ul/li[+str(sub_k)+]/em/a/span/text()).extract()[0]
            # 副导航栏链接
            sub_navigation_item[sub_navigation_url] = response.xpath(//*[@id="nodeNav"]/div/ul/li[+str(sub_k)+]/em/a/@href).extract()[0]

        # 获取每页电影条目数长度
        movie_name_tr_array = response.xpath(/html/body/div[2]/table[1]/tr/td[1]/table[2]/tbody/tr).extract()
        for i_k in range(1, len(movie_name_tr_array)):
            # 子链接
            str_sub_url = /html/body/div[2]/table[1]/tr/td[1]/table[2]/tbody/tr[+str(i_k)+]/td[1]/a/@href
            m_link = self.web_pre_url + response.xpath(str_sub_url).extract()[0]
            yield scrapy.Request(url=m_link, callback=self.parse_links, dont_filter=True)

        # 解析下一页
        next_link = response.xpath(//*[@class="pagegbk"]/@href).extract()
        if next_link:
            if len(next_link) == 1:
                next_link = next_link[0]
            else:
                next_link = next_link[1]
            yield scrapy.Request(self.web_pre_url + next_link, callback=self.parse)

    # 爬取子链接
    def parse_links(self, response):
        torrent_item = TorrentItem()
        # 标题
        torrent_item[torrent_title] = self.check_xpath_value(response, /html/body/div[2]/table[1]/tbody/tr/td/font/text())
        # 影片名称
        torrent_item[torrent_name] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[1]/font[1]/text())
        # 导演
        torrent_item[torrent_director] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[1]/font[2]/text())
        # 影片演员
        torrent_item[torrent_actor] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[1]/span/font[2]/text())
        # 语言
        torrent_item[torrent_language] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[1]/font[3]/text())
        # 影片类型
        torrent_item[torrent_type] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[1]/font[4]/text())
        # 影片地区
        torrent_item[torrent_region] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[1]/font[5]/text())
        # 更新时间
        torrent_item[torrent_update_time] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[1]/font[6]/text())
        # 影片状态
        torrent_item[torrent_status] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[1]/font[7]/text())
        # 上映日期
        torrent_item[torrent_show_time] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[1]/font[8]/text())
        # 剧情介绍
        torrent_item[torrent_introduction] = self.check_xpath_value(response, /html/body/div[2]/table[2]/tbody/tr/td/div[2]/text())
        # 影片地址
        torrent_item[torrent_url] = self.check_xpath_value(response, //*[@id="plist"]/table[2]/tbody/tr[2]/td/ul/li/input/@value)

        # 获取当前时间并格式化
        current_date = time.strftime(%Y-%m-%d, time.localtime())
        print(current_date = %s % str(current_date))
        print(torrent_update_time = %s % torrent_item[torrent_update_time])
        # 如果不是当天的就不爬取,并且计数
        if torrent_item[torrent_update_time] == str(current_date):
            yield torrent_item
        else:
            self.count = self.count + 1
            # 判断计数是否超过50,超过就不爬取了
            if self.count > 1:
                # logging.info("计数超过10,停止爬虫")
                self.crawler.engine.close_spider(self, ‘计数超过10,停止爬虫!‘)
            pass

    # 判断是否为空
    @staticmethod
    def check_xpath_value(response, xpath_url):
        xpath_value = response.xpath(xpath_url).extract()
        if xpath_value:
            if xpath_value[0].strip() != ‘‘:
                return xpath_value[0]
            else:
                return "null"
        else:
            return "null"

注意以上代码中标红的地方:

self.crawler.engine.close_spider(self, ‘计数超过10,停止爬虫!‘)

1,此行代码是写在spider文件中的

2,虽然这一行代码会停止爬虫,但是这一行代码的停止并不是立即停止

原因是因为当我们不更改爬虫的setting.py文件的时候,默认配置是:

# Configure maximum concurrent requests performed by Scrapy (default: 16)
# CONCURRENT_REQUESTS = 32

含义就是:Scrapy downloader 并发请求(concurrent requests)的最大值,默认: 16

那么这个时候的问题来了,按照以上的写法,在队列里就已经有十几个请求了,你停止之后,这十几个请求依旧会执行下去,所以并不是立即停止,如果想改变的话,就必须改变此项配置,设为:

CONCURRENT_REQUESTS = 1

 

具体scrapy爬虫原理请自行百度,并请自行调试,谢谢~

 

以上是关于scrapy主动退出爬虫的代码片段(python3)的主要内容,如果未能解决你的问题,请参考以下文章

Python3爬虫Scrapy+MongoDB+MySQL

scrapy中主动触发关闭爬虫的方法

Scrapy爬虫:scrapy架构及原理

python3下scrapy爬虫(第九卷:scrapy数据存储进JSON文件)

python3下scrapy爬虫(第十四卷:scrapy+scrapy_redis+scrapyd打造分布式爬虫之执行)

scrapy 主动停止爬虫