我正在编写Scrapy Spider来浏览旅游网站。该网站的结构如下:
Continents
North America
USA
lat: 123
long: 456
Canada
lat: 123
long: 456
South America
Brazil
lat: 456
long: 789
Peru
lat: 123
long: 456
我已经找到了如何抓取每个国家/地区页面并使用下面的脚本获取纬度/长信息,但我遇到的困难是存储信息。
import scrapy
class WorldSpider(scrapy.Spider):
name = "world"
def start_requests(self):
urls = [
'www.world.com'
]
for url in urls:
# yield scrapy.Request(url=url, callback=self.parse)
yield scrapy.Request(url=url, callback=self.parse_region)
def parse(self, response):
for link in response.css(CONTINENT_SELECTOR):
continent = link.css('a::attr(href)').extract_first()
if continent is not None:
continent = response.urljoin(continent)
yield response.follow(continent, callback=self.parse_continent)
def parse_continent(self, continent_response):
country_urls = continent_response.css(COUNTRY_SELECTOR)
if len(country_urls) == 0:
# This if-statement is entered when the Spider is at a country web page (e.g. USA, Canada, etc.).
# TODO figure out how to store this to text file or append to JSON object
yield {
'country': continent_response.css(TITLE_SELECTOR).extract_first(),
'latitude' : continent_response.css(LATITUDE_SELECTOR).extract_first(),
'longitude' : continent_response.css(LONGITUDE_SELECTOR).extract_first()
}
for link in country_urls:
country = link.css('a::attr(href)').extract_first()
if area is not None:
yield continent_response.follow(continent_response.urljoin(area), callback=self.parse_continent)
如何将此信息写入文件或JSON对象?理想情况下,我希望数据的结构能够捕获网站的结构。
示例:
{
"continents": [
{"North America" : [
{"country" : {"title": "USA", "latitude" : 123, "longitude" : 456}},
{"country" : {"title": "Canada", "latitude" : 123, "longitude" : 456}}
]},
{"South America" : [
{"country" : {"title": "Brazil", "latitude" : 456, "longitude" : 789}},
{"Peru" : {"title": "Peru", "latitude" : 123, "longitude" : 456}}
]}
]
}
如何修改我的蜘蛛以实现上述目标?
答案 0 :(得分:1)
将数据存储在文件中可以通过两种方式完成。首先是@Jan提到的,使用JsonWritePipeline,当scrapy spider运行多次并且每次都用于附加到文件时,建议使用这种方法。
以下是此类执行的示例:
with open(filename, 'a') as f:
f.write(response.body)
self.log('Saved file %s' % filename)
虽然最简单的方法是使用Feed Export选项,以便更容易实现。
Feed Exports允许您使用多个序列化格式和存储后端生成包含已删除项目的Feed。 对于序列化已删除的数据,Feed导出使用Item 出口商。开箱即用支持这些格式:
JSON JSON lines CSV XML
以下是使用FileExport将数据存储为JSON文件的示例:
$scrapy crawl myExample -o output.json
注意: Scrapy会附加到给定文件,而不是覆盖其内容。如果 您运行此命令两次而不删除第二个之前的文件 时间,你最终会得到一个破碎的JSON文件。
对于JSON中数据的结构,我更喜欢使用Item,因为它为您提供了一个非常清晰的结构,并且有许多深度JSON可用于验证结构
对于您的实现,结构应声明为:
import scrapy
class Address(scrapy.Item):
title = scrapy.Field()
latitude = scrapy.Field()
longitude = scrapy.Field()
class Place(scrapy.Item):
country = scrapy.Field() #object of Address
class Continents(scrapy.Item):
name = scrapy.Field() #array of Place
我将让你弄清楚如何实现它; - )
答案 1 :(得分:-1)
Scrapy通过Feed Exports提供此功能,允许您使用多个序列化格式和存储后端生成带有已删除项目的Feed。
scrapy crawl WorldSpider -o name.json -t json
将保存已解析的项目。