Scrapy CSS选择器

时间:2017-03-16 08:18:16

标签: python scrapy

我正在学习如何使用scrapy,但我遇到了一些问题。我按照在线教程编写了这段代码,以便更多地了解它。

import scrapy

class BrickSetSpider(scrapy.Spider):
name = 'brick_spider'
start_urls = ['http://brickset.com/sets/year-2016']

def parse(self, response):
    SET_SELECTOR = '.set'
    for brickset in response.css(SET_SELECTOR):

        NAME_SELECTOR = 'h1 a ::text'
        PIECES_SELECTOR = './/dl[dt/text() = "Pieces"]/dd/a/text()'
        MINIFIGS_SELECTOR = './/dl[dt/text() = "Minifigs"]/dd[2]/a/text()'
        PRICE_SELECTOR  =  './/dl[dt/text() = "RRP"]/dd[3]/text()'
        IMAGE_SELECTOR = 'img ::attr(src)'
        yield {
            'name': brickset.css(NAME_SELECTOR).extract_first(),
            'pieces': brickset.xpath(PIECES_SELECTOR).extract_first(),
            'minifigs': brickset.xpath(MINIFIGS_SELECTOR).extract_first(),
    'retail price': brickset.xpath(PRICE_SELECTOR).extract_first(),
            'image': brickset.css(IMAGE_SELECTOR).extract_first(),
        }

    NEXT_PAGE_SELECTOR = '.next a ::attr(href)'
    next_page = response.css(NEXT_PAGE_SELECTOR).extract_first()
    if next_page:
        yield scrapy.Request(
            response.urljoin(next_page),
            callback=self.parse
        )

由于这些网站划分了多年来列出的产品,而且此代码仅抓取2016年的数据,因此我决定对其进行扩展并分析前几年的数据。代码的想法是:

PREVIOUS_YEAR_SELECTOR = '...'
previous_year= response.css(PREVIOUS_YEAR_SELECTOR).extract_first()
if previous_year:
    yield scrapy.Request(
        response.urljoin(previous_year),
                callback=self.parse
            )

我尝试了不同的东西,但我真的不知道写什么而不是'......' 我也试过xpath但似乎没什么用。

2 个答案:

答案 0 :(得分:0)

也许你想利用href属性的结构?它似乎遵循结构/sets/year-YYYY。通过这个,您可以使用基于正则表达式的选择器或 - 如果您像我一样懒惰 - 只需contains()

XPath://a[contains(@href,"/sets/year-")]/@href

我不确定CSS是否也可以。因此...可以填充:

PREVIOUS_YEAR_SELECTOR_XPATH = '//a[contains(@href,"/sets/year-")]/@href'
previous_year = response.xpath(PREVIOUS_YEAR_SELECTOR).extract_first()

但我认为你会这么久,所以也许你想要循环链接:

PREVIOUS_YEAR_SELECTOR_XPATH = '//a[contains(@href,"/sets/year-")]/@href'
for previous_year in response.xpath(PREVIOUS_YEAR_SELECTOR):
    yield scrapy.Request(response.urljoin(previous_year), callback=self.parse)

我认为你的方式很好。谷歌提供符合您需求的CSS / XPATH备忘单,并查看FirePath扩展名或类似内容。它大大加快了选择器的设置:)

答案 1 :(得分:0)

这里至少有两个选项。 第一种是使用通用CrawlSpider 并定义要提取和关注的链接。 像这样:

class BrickSetSpider(scrapy.CrawlSpider):
    name = 'brick_spider'
    start_urls = ['http://brickset.com/sets']
    rules = (
        Rule(LinkExtractor(
            allow=r'\/year\-[\d]{4}'), callback='parse_bricks', follow=True),
    )
#Your method renamed to parse_bricks goes here

注意:您需要将parse方法重命名为其他名称,例如'parse_bricks',因为CrawlSpider本身使用parse方法。

第二个选项是将start_urls设置为包含所有年份集链接的页面http://brickset.com/browse/sets,并添加解析这些链接的方法:

class BrickSetSpider(scrapy.Spider):
    name = 'brick_spider'
    start_urls = ['http://brickset.com/browse/sets']

    def parse(self, response):
        links = response.xpath(
            '//a[contains(@href, "/sets/year")]/@href').extract()
        for link in links:
            yield scrapy.Request(response.urljoin(link), callback=self.parse_bricks)

    # Your method renamed to parse_bricks goes here