2012-10-11 95 views
21

我有以下形式的網址:scrapy - 這是分頁解析項目

example.com/foo/bar/page_1.html 

總共有53頁是,他們每個人都有〜20行。

我基本上想要從所有頁面獲取所有行,即〜53 * 20個項目。

我在parse方法工作的代碼,它分析一個網頁,並且還進入每個項目一個頁面更深,以獲取有關該項目的詳細信息:

def parse(self, response): 
    hxs = HtmlXPathSelector(response) 

    restaurants = hxs.select('//*[@id="contenido-resbus"]/table/tr[position()>1]') 

    for rest in restaurants: 
     item = DegustaItem() 
     item['name'] = rest.select('td[2]/a/b/text()').extract()[0] 
     # some items don't have category associated with them 
     try: 
     item['category'] = rest.select('td[3]/a/text()').extract()[0] 
     except: 
     item['category'] = '' 
     item['urbanization'] = rest.select('td[4]/a/text()').extract()[0] 

     # get profile url 
     rel_url = rest.select('td[2]/a/@href').extract()[0] 
     # join with base url since profile url is relative 
     base_url = get_base_url(response) 
     follow = urljoin_rfc(base_url,rel_url) 

     request = Request(follow, callback = parse_profile) 
     request.meta['item'] = item 
     return request 


    def parse_profile(self, response): 
    item = response.meta['item'] 
    # item['address'] = figure out xpath 
    return item 

的問題是,我該怎麼辦抓取每個頁面?

example.com/foo/bar/page_1.html 
example.com/foo/bar/page_2.html 
example.com/foo/bar/page_3.html 
... 
... 
... 
example.com/foo/bar/page_53.html 

回答

33

你有兩個選擇來解決你的問題。一般是使用yield來生成新的請求,而不是return。這樣,您可以從單個回調中發出多個新請求。檢查第二個例子http://doc.scrapy.org/en/latest/topics/spiders.html#basespider-example

你的情況有可能是一個簡單的解決方案:

class MySpider(BaseSpider): 
    start_urls = ['http://example.com/foo/bar/page_%s.html' % page for page in xrange(1,54)] 
+0

start_urls想法很棒。非常感謝 – AlexBrand

+0

優秀的答案。非常感謝。 scrapy網站上的LinkExtractor並不適合我。這樣做。 –

+0

如何檢查頁面是否找不到。它只有53頁。但如果我叫'xrange(1,60)'。 – user1586957

11

您可以使用CrawlSpider代替BaseSpider和使用SgmlLinkExtractor提取的網頁:剛剛從這樣的圖案產生開始URS名單在分頁。

例如:

start_urls = ["www.example.com/page1"] 
rules = (Rule (SgmlLinkExtractor(restrict_xpaths=('//a[@class="next_page"]',)) 
       , follow= True), 
      Rule (SgmlLinkExtractor(restrict_xpaths=('//div[@class="foto_imovel"]',)) 
       , callback='parse_call') 
    ) 

的第一條規則告訴scrapy跟隨包含在XPath表達式的鏈接,第二條規則告訴scrapy致電parse_call中包含XPath表達式的鏈接,在你想要的情況下解析每個頁面中的內容。

欲瞭解更多信息請參閱文檔:http://doc.scrapy.org/en/latest/topics/spiders.html#crawlspider

+0

我遇到了類似的問題,我所做的就像你說的,但它仍然只是抓取start_url頁面。 –

+0

SgmlLinkExtractors和contrib模塊中的所有其他類都會引發錯誤。請改用LinkExtracor類。 –

6

可以有兩個用例的「scrapy - 這是分頁解析項目」。 A)

A)。我們只是想在表格中移動並獲取數據。這是相對直接的。

class TrainSpider(scrapy.Spider): 
    name = "trip" 
    start_urls = ['somewebsite'] 
    def parse(self, response): 
     ''' do something with this parser ''' 
     next_page = response.xpath("//a[@class='next_page']/@href").extract_first() 
     if next_page is not None: 
      next_page = response.urljoin(next_page) 
      yield scrapy.Request(next_page, callback=self.parse) 

觀察最後4行。這裏

  1. 我們從'下一步'分頁按鈕獲得下一頁鏈接表單下一頁xpath。
  2. 如果檢查條件是否不是分頁結束。
  3. 加入此鏈接(我們得到了第1步)與主要URL使用url加入
  4. 遞歸調用parse回調方法。

B)不僅我們想要跨頁面移動,而且還想從該頁面中的一個或多個鏈接提取數據。

class StationDetailSpider(CrawlSpider): 
    name = 'train' 
    start_urls = [someOtherWebsite] 
    rules = (
     Rule(LinkExtractor(restrict_xpaths="//a[@class='next_page']"), follow=True), 
     Rule(LinkExtractor(allow=r"/trains/\d+$"), callback='parse_trains') 
    ) 
    def parse_trains(self, response): 
    '''do your parsing here''' 

Overhere,觀察到:

  1. 我們使用CrawlSpider

  2. 我們已經設置爲scrapy.Spider父類的 '規則'

    一)第一條規則,只是檢查是否有'next_page'可用並且遵循它。

    b)第二個規則請求頁面上所有格式爲/trains/12343的鏈接,然後調用parse_trains來執行和解析操作。

  3. 重要:請注意,我們不希望在這裏使用常規parse方法,我們使用CrawlSpider子類。該課程還有一個parse方法,因此我們不希望覆蓋該方法。只要記住將您的回撥方式命名爲parse以外的方法即可。