2017-12-08 8 views
0

ハイパーリンクのページ区切りボタンがないレビューサイトにページを分けようとしています。私は、各リンクのページ数をページ付けし、ハードコーディングするロジックを書いています。しかし、私はそれがstart_requestsの特定のリンクのページ数として掻き集めた情報を使用することが可能かどうかと思っています。ここ一度ページ数を削り取った後に改ページする方法は? (Scrapy)

スパイダーコード(2つのリンクを経由ページ付けする):

class TareviewsSpider(scrapy.Spider): 
    name = 'tareviews' 
    allowed_domains = ['tripadvisor.com'] 
    # start_urls = [] 

    def start_requests(self): 
     for page in range(0,395,5): 
      yield self.make_requests_from_url('https://www.tripadvisor.com/Hotel_Review-g60795-d102542-Reviews-or{}-Courtyard_Philadelphia_Airport-Philadelphia_Pennsylvania.html'.format(page)) 
     for page in range(0,1645,5): 
      yield self.make_requests_from_url('https://www.tripadvisor.com/Hotel_Review-g60795-d122332-Reviews-or{}-The_Ritz_Carlton_Philadelphia-Philadelphia_Pennsylvania.html'.format(page)) 

    def parse(self, response): 
     for idx,review in enumerate(response.css('div.review-container')): 
      item = { 
       'num_reviews': response.css('span.reviews_header_count::text')[0].re(r'\d{0,3}\,?\d{1,3}'), 
       'hotel_name': response.css('h1.heading_title::text').extract_first(), 
       'review_title': review.css('span.noQuotes::text').extract_first(), 
       'review_body': review.css('p.partial_entry::text').extract_first(), 
       'review_date': review.xpath('//*[@class="ratingDate relativeDate"]/@title')[idx].extract(), 
       'num_reviews_reviewer': review.css('span.badgetext::text').extract_first(), 
       'reviewer_name': review.css('span.scrname::text').extract(), 
       'bubble_rating': review.xpath("//div[contains(@class, 'reviewItemInline')]//span[contains(@class, 'ui_bubble_rating')]/@class")[idx].re(r'(?<=ui_bubble_rating bubble_).+?(?=0)') 
      } 
      yield item 

'num_reviews'は、各リンクの最後のページ数の値です。 for loopstart_requestsでは、3951645です。

これは可能ですか?可能であればヘッドレスブラウザを避けたいと思います。ありがとう!

+0

'parse()'では、新しいURLを指定してyield request()を使ってリストに追加することができます。 – furas

+0

この場合の解析である 'num_reviews'は、最後のページの番号を返します。 'yield Request()'はこの文脈では動作しないと考えています。b.c総ページ数がわかると、ページネーションを実行するループが必要です。 – hackerman

+0

ページ数を知っていれば、ループで 'yield Request(url = ...)'を使うことができます。 – furas

答えて

1

私はこのコード

私は通常のURLを使用して作られた - -or{}なし - ページを取得し、レビューの数を見つけることを。
次に、私は-or{}をURLに追加します。これはどこにでもあり、レビュー付きページへのURLを生成することができます。
そして、私はforループとRequest()を使ってレビューのページを取得します。
レビューは異なる方法で解析されている - 私は完全なプロジェクトなしでそれを実行するためにscrapy.crawler.CrawlerProcess()を使用してコードでparse_reviews()


は、誰もが簡単にそれを実行してテストすることができます。 Googleの検索結果でより良いポジションを得るために - URLでのみSEOためのものであるあなたが

https://www.tripadvisor.com/g60795-d102542 
https://www.tripadvisor.com/g60795-d102542-or0 
https://www.tripadvisor.com/g60795-d102542-or5 

他の単語をURL必要ページを取得するには:

それはところでoutput.csv

import scrapy 

class TareviewsSpider(scrapy.Spider): 

    name = 'tareviews' 
    allowed_domains = ['tripadvisor.com'] 

    start_urls = [ # without `-or{}` 
     'https://www.tripadvisor.com/Hotel_Review-g60795-d102542-Reviews-Courtyard_Philadelphia_Airport-Philadelphia_Pennsylvania.html', 
     'https://www.tripadvisor.com/Hotel_Review-g60795-d122332-Reviews-The_Ritz_Carlton_Philadelphia-Philadelphia_Pennsylvania.html', 
    ] 

    def parse(self, response): 
     # get number of reviews 
     num_reviews = response.css('span.reviews_header_count::text').extract_first() 
     num_reviews = num_reviews[1:-1] # remove `()` 
     num_reviews = num_reviews.replace(',', '') # remove `,` 
     num_reviews = int(num_reviews) # convert to integer 
     print('num_reviews:', num_reviews, type(num_reviews)) 

     # create template to generate urls to pages with reviews 
     url = response.url.replace('.html', '-or{}.html') 
     print('template:', url) 

     # add requests to list 
     for offset in range(0, num_reviews, 5): 
      print('url:', url.format(offset)) 
      yield scrapy.Request(url=url.format(offset), callback=self.parse_reviews) 

    def parse_reviews(self, response): 
     print('reviews') 
     for idx,review in enumerate(response.css('div.review-container')): 
      item = { 
       'num_reviews': response.css('span.reviews_header_count::text')[0].re(r'\d{0,3}\,?\d{1,3}'), 
       'hotel_name': response.css('h1.heading_title::text').extract_first(), 
       'review_title': review.css('span.noQuotes::text').extract_first(), 
       'review_body': review.css('p.partial_entry::text').extract_first(), 
       'review_date': review.xpath('//*[@class="ratingDate relativeDate"]/@title')[idx].extract(), 
       'num_reviews_reviewer': review.css('span.badgetext::text').extract_first(), 
       'reviewer_name': review.css('span.scrname::text').extract(), 
       'bubble_rating': review.xpath("//div[contains(@class, 'reviewItemInline')]//span[contains(@class, 'ui_bubble_rating')]/@class")[idx].re(r'(?<=ui_bubble_rating bubble_).+?(?=0)') 
      } 
      yield item 


# --- run without project --- 

import scrapy.crawler 

c = scrapy.crawler.CrawlerProcess({ 
    "FEED_FORMAT": 'csv', 
    "FEED_URI": 'output.csv', 
}) 
c.crawl(TareviewsSpider) 
c.start()) 

内のデータが保存されます。

関連する問題