我正在学习如何使用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但似乎没什么用。
答案 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