scrapy可以跳过空数据并保持抓取的错误吗?

时间:2019-05-29 13:41:51

标签: python scrapy

我想从其站点地图中刮取产品页面,产品页面是相似的,但并非所有页面都是相同的。

例如

产品A https://www.vitalsource.com/products/environment-the-science-behind-the-stories-jay-h-withgott-matthew-v9780134446400

产品B https://www.vitalsource.com/products/abnormal-psychology-susan-nolen-hoeksema-v9781259765667

我们可以看到产品A有副标题,而另一个没有副标题。

因此,当我尝试刮取所有产品页面时遇到错误。

我的问题是,有没有办法让Spider跳过不返回数据的错误?

有一个简单的方法可以绕过它。那不是使用strip() 但我想知道是否有更好的方法来完成这项工作。

import scrapy
import re
from VitalSource.items import VitalsourceItem
from scrapy.selector import Selector
from scrapy.spiders import SitemapSpider



class VsSpider(SitemapSpider):
    name = 'VS'
    allowed_domains = ['vitalsource.com']
    sitemap_urls = ['https://storage.googleapis.com/vst-stargate-production/sitemap/sitemap1.xml.gz']
    sitemap_rules = [
        ('/products/', 'parse_product'),
    ]
    def parse_product(self, response):
        selector = Selector(response=response)
        item = VitalsourceItem()
        item['Ebook_Title'] = response.css('.product-overview__title-header::text').extract()[1].strip
        item['Ebook_SubTitle'] = response.css("div.subtitle.subtitle-pdp::text").extract().strip
        print(item)
        return item

错误消息

    item['Ebook_SubTitle'] = response.css("div.subtitle.subtitle-pdp::text").extract().strip
AttributeError: 'list' object has no attribute 'strip'

3 个答案:

答案 0 :(得分:2)

由于只需要一个字幕,因此可以使用get()并将默认值设置为空字符串。这将使您免于将strip()函数应用于空元素的错误。

item['Ebook_SubTitle'] = response.css("div.subtitle.subtitle-pdp::text").get('').strip()

答案 1 :(得分:0)

您可以在提取之前检查是否返回了值:

if response.css("div.subtitle.subtitle-pdp::text"):
    item['Ebook_SubTitle'] = response.css("div.subtitle.subtitle-pdp::text").get().strip

这样,只有在返回值的情况下,subTitle代码行才会运行...

答案 2 :(得分:-1)

通常,如果回调引发异常,则scrapy不会停止爬网。例如:

def start_requests(self):
    for i in range(10):
        yield Requst(
            f'http://example.org/page/{i}',
            callback=self.parse,
            errback=self.errback,
        )

def parse(self, response):
    # first page 
    if 'page/1' in response.request.url:
        raise ValueError()
    yield {'url': response.url}

def errback(self, failure): 
    print(f"oh no, failed to parse {failure.request}")

在此示例中,将发出10个请求,并且将刮取9个项目,但其中1个将失败并得到errback

对于您而言,您没有什么可担心的-任何未引发异常的请求都将按期进行抓取,对于那些请求,您只会在终端/日志中看到异常回溯。