2017-06-14 134 views
2

我正在寫一個Scrapy蜘蛛遍歷旅遊網站。該網站的結構如下:蟒蛇Scrapy網絡爬行和刮

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

您需要[**管道**] (https://doc.scrapy.org/zh/latest/topics/item-pipeline.html#write-items-to-a-json-file) – Jan

+0

@Jan感謝您的輸入。我仍然在使用Scrapy,因此瞭解文檔中的內容很有幫助。謝謝! – GobiasKoffi

回答

1

將數據存儲在文件中可以用兩種方法完成。首先就像@Jan提到的那樣,使用JsonWritePipeline,在scrapy蜘蛛多次運行時推薦使用這種方法,並且每次都使用該方法追加到文件中。

以下是這樣執行的例子:

with open(filename, 'a') as f: 
      f.write(response.body) 
self.log('Saved file %s' % filename) 

雖然最簡單的方法是使用Feed Export選項,可以更容易實現。

Feed Export允許您使用多個序列化格式和存儲後端生成包含已刪除項目的提要。 爲了序列化所刮取的數據,供給導出使用項目 導出器。這些格式的支持開箱即用:

JSON 
    JSON lines 
    CSV 
    XML 

下面是使用FileExport以數據存儲爲一個JSON文件的例子:

$scrapy crawl myExample -o output.json 

注: Scrapy追加到一個而不是覆蓋其內容。如果 您運行此命令兩次而不刪除第二個 時間之前的文件,您將最終得到一個損壞的JSON文件。

至於在JSON數據的結構,我喜歡與Item工作,因爲它爲您提供了記,並與許多深度JSONs最好驗證結構非常清晰的結構。

對於您的實現,作爲結構應該聲明:

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

Scrapy通過Feed出口提供了這種功能,它允許您使用多個序列化格式和存儲後端生成包含已刪除項目的提要。

scrapy crawl WorldSpider -o name.json -t json 

將保存解析的項目。

+0

感謝您的輸入。我將在Scrapy文檔中查看Feed Export。 – GobiasKoffi