Scrapy spider finding one “Next” button but not the otherScrapy - how to manage cookies/sessionsGot runUntilCurrent Error Message when running Scrapy Spider with SeleniumScrapy: output comparison of two spidersPython Scrapy and yieldingCannot access certain reddit data through scrapy shellScrapy XHR Pagination on TripAdvisorusing scrapy creating a spider and unable to store data to csvConfused about scrapy and XpathHow to reach to a very deeply nested A HREF for my spider to find the NEXT button?scrapy add data to the json file from different functions

Remove everything except csv file Bash Script

LocalDate.plus Incorrect Answer

Two researchers want to work on the same extension to my paper. Who to help?

As programers say: Strive to be lazy

What does i386 mean on macOS Mojave?

Is it a Munchausen Number?

Why can't RGB or bicolour LEDs produce a decent yellow?

Why does TypeScript pack a Class in an IIFE?

Does the 500 feet falling cap apply per fall, or per turn?

What is the airplane type in this formation seen above Eugene, Oregon?

How to align underlines in a cases environment

What are some possible reasons that a father's name is missing from a birth certificate - England?

Ex-manager wants to stay in touch, I don't want to

Delta TSA-Precheck status removed

Why was the Ancient One so hesitant to teach Dr. Strange the art of sorcery?

How could a Lich maintain the appearance of being alive without magic?

How do I get past a 3-year ban from overstay with VWP?

51% attack - apparently very easy? refering to CZ's "rollback btc chain" - How to make sure such corruptible scenario can never happen so easily?

How could we transfer large amounts of energy sourced in space to Earth?

Cropping a message using array splits

Why was this sacrifice sufficient?

How to pronounce "r" after a "g"?

Can 'sudo apt-get remove [write]' destroy my Ubuntu?

How are one-time password generators like Google Authenticator different from having two passwords?



Scrapy spider finding one “Next” button but not the other


Scrapy - how to manage cookies/sessionsGot runUntilCurrent Error Message when running Scrapy Spider with SeleniumScrapy: output comparison of two spidersPython Scrapy and yieldingCannot access certain reddit data through scrapy shellScrapy XHR Pagination on TripAdvisorusing scrapy creating a spider and unable to store data to csvConfused about scrapy and XpathHow to reach to a very deeply nested A HREF for my spider to find the NEXT button?scrapy add data to the json file from different functions






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








2















I am writing a spider to scrape a popular reviews website :-) This is my first attempt at writing a Scrapy spider.



The top level is a list of restaurants (I call this "top level"), which appear 30 at a time. My spider accesses each link and then "clicks next" to get the next 30, and so on. This part is working as my output does contain thousands of restaurants, not just the first 30.



I then want it to "click" on the link to each restaurant page ("restaurant level"), but this contains only truncated versions of the reviews, so I want it to then "click" down a further level (to "review level") and scrape the reviews from there, which appear 5 at a time with another "next" button. This is the only "level" from which I am extracting anything - the other levels just have links to access to get to the reviews and other info I want.



Most of this is working as I am getting all the information I want, but only for the first 5 reviews per restaurant. It is not "finding" the "next" button on the bottom "review level".



I have tried changing the order of commands within the parse method, but other than that I am coming up short of ideas! My xpaths are fine so it must be something to do with structure of the spider.



My spider looks thus:



import scrapy
from scrapy.http import Request

class TripSpider(scrapy.Spider):

name = 'tripadvisor'
allowed_domains = ['tripadvisor.co.uk']
start_urls = ['https://www.tripadvisor.co.uk/Restaurants-g187069-Manchester_Greater_Manchester_England.html']
custom_settings =
'DOWNLOAD_DELAY': 1,
# 'DEPTH_LIMIT': 3,
'AUTOTHROTTLE_TARGET_CONCURRENCY': 0.5,
'USER_AGENT': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
# 'DEPTH_PRIORITY': 1,
# 'SCHEDULER_DISK_QUEUE': 'scrapy.squeues.PickleFifoDiskQueue',
# 'SCHEDULER_MEMORY_QUEUE': 'scrapy.squeues.FifoMemoryQueue'


def scrape_review(self, response):
restaurant_name_review = response.xpath('//div[@class="wrap"]//span[@class="taLnk "]//text()').extract()
reviewer_name = response.xpath('//div[@class="username mo"]//text()').extract()
review_rating = response.xpath('//div[@class="wrap"]/div[@class="rating reviewItemInline"]/span[starts-with(@class,"ui_bubble_rating")]').extract()
review_title = response.xpath('//div[@class="wrap"]//span[@class="noQuotes"]//text()').extract()
full_reviews = response.xpath('//div[@class="wrap"]/div[@class="prw_rup prw_reviews_text_summary_hsx"]/div[@class="entry"]/p').extract()
review_date = response.xpath('//div[@class="prw_rup prw_reviews_stay_date_hsx"]/text()[not(parent::script)]').extract()
restaurant_name = response.xpath('//div[@id="listing_main_sur"]//a[@class="HEADING"]//text()').extract() * len(full_reviews)
restaurant_rating = response.xpath('//div[@class="userRating"]//@alt').extract() * len(full_reviews)
restaurant_review_count = response.xpath('//div[@class="userRating"]//a//text()').extract() * len(full_reviews)

for rvn, rvr, rvt, fr, rd, rn, rr, rvc in zip(reviewer_name, review_rating, review_title, full_reviews, review_date, restaurant_name, restaurant_rating, restaurant_review_count):
reviews_dict = dict(zip(['reviewer_name', 'review_rating', 'review_title', 'full_reviews', 'review_date', 'restaurant_name', 'restaurant_rating', 'restaurant_review_count'], (rvn, rvr, rvt, fr, rd, rn, rr, rvc)))
yield reviews_dict
# print(reviews_dict)

def parse(self, response):
### The parse method is what is actually being repeated / iterated
for review in self.scrape_review(response):
yield review
# print(review)

# access next page of resturants
next_page_restaurants = response.xpath('//a[@class="nav next rndBtn ui_button primary taLnk"]/@href').extract_first()
next_page_restaurants_url = response.urljoin(next_page_restaurants)
yield Request(next_page_restaurants_url)
print(next_page_restaurants_url)

# access next page of reviews
next_page_reviews = response.xpath('//a[@class="nav next taLnk "]/@href').extract_first()
next_page_reviews_url = response.urljoin(next_page_reviews)
yield Request(next_page_reviews_url)
print(next_page_reviews_url)

# access each restaurant page:
url = response.xpath('//div[@id="EATERY_SEARCH_RESULTS"]/div/div/div/div/a[@target="_blank"]/@href').extract()
for url_next in url:
url_full = response.urljoin(url_next)
yield Request(url_full)

# "accesses the first review to get to the full reviews (not the truncated versions)"
first_review = response.xpath('//a[@class="title "]/@href').extract_first() # extract first used as I only want to access one of the links on this page to get down to "review level"
first_review_full = response.urljoin(first_review)
yield Request(first_review_full)
# print(first_review_full)










share|improve this question
























  • Can you post an actual link you're trying to scrape?

    – malberts
    Mar 23 at 14:28











  • Sure, my start URL is tripadvisor.co.uk/…

    – Dave C
    Mar 23 at 16:15

















2















I am writing a spider to scrape a popular reviews website :-) This is my first attempt at writing a Scrapy spider.



The top level is a list of restaurants (I call this "top level"), which appear 30 at a time. My spider accesses each link and then "clicks next" to get the next 30, and so on. This part is working as my output does contain thousands of restaurants, not just the first 30.



I then want it to "click" on the link to each restaurant page ("restaurant level"), but this contains only truncated versions of the reviews, so I want it to then "click" down a further level (to "review level") and scrape the reviews from there, which appear 5 at a time with another "next" button. This is the only "level" from which I am extracting anything - the other levels just have links to access to get to the reviews and other info I want.



Most of this is working as I am getting all the information I want, but only for the first 5 reviews per restaurant. It is not "finding" the "next" button on the bottom "review level".



I have tried changing the order of commands within the parse method, but other than that I am coming up short of ideas! My xpaths are fine so it must be something to do with structure of the spider.



My spider looks thus:



import scrapy
from scrapy.http import Request

class TripSpider(scrapy.Spider):

name = 'tripadvisor'
allowed_domains = ['tripadvisor.co.uk']
start_urls = ['https://www.tripadvisor.co.uk/Restaurants-g187069-Manchester_Greater_Manchester_England.html']
custom_settings =
'DOWNLOAD_DELAY': 1,
# 'DEPTH_LIMIT': 3,
'AUTOTHROTTLE_TARGET_CONCURRENCY': 0.5,
'USER_AGENT': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
# 'DEPTH_PRIORITY': 1,
# 'SCHEDULER_DISK_QUEUE': 'scrapy.squeues.PickleFifoDiskQueue',
# 'SCHEDULER_MEMORY_QUEUE': 'scrapy.squeues.FifoMemoryQueue'


def scrape_review(self, response):
restaurant_name_review = response.xpath('//div[@class="wrap"]//span[@class="taLnk "]//text()').extract()
reviewer_name = response.xpath('//div[@class="username mo"]//text()').extract()
review_rating = response.xpath('//div[@class="wrap"]/div[@class="rating reviewItemInline"]/span[starts-with(@class,"ui_bubble_rating")]').extract()
review_title = response.xpath('//div[@class="wrap"]//span[@class="noQuotes"]//text()').extract()
full_reviews = response.xpath('//div[@class="wrap"]/div[@class="prw_rup prw_reviews_text_summary_hsx"]/div[@class="entry"]/p').extract()
review_date = response.xpath('//div[@class="prw_rup prw_reviews_stay_date_hsx"]/text()[not(parent::script)]').extract()
restaurant_name = response.xpath('//div[@id="listing_main_sur"]//a[@class="HEADING"]//text()').extract() * len(full_reviews)
restaurant_rating = response.xpath('//div[@class="userRating"]//@alt').extract() * len(full_reviews)
restaurant_review_count = response.xpath('//div[@class="userRating"]//a//text()').extract() * len(full_reviews)

for rvn, rvr, rvt, fr, rd, rn, rr, rvc in zip(reviewer_name, review_rating, review_title, full_reviews, review_date, restaurant_name, restaurant_rating, restaurant_review_count):
reviews_dict = dict(zip(['reviewer_name', 'review_rating', 'review_title', 'full_reviews', 'review_date', 'restaurant_name', 'restaurant_rating', 'restaurant_review_count'], (rvn, rvr, rvt, fr, rd, rn, rr, rvc)))
yield reviews_dict
# print(reviews_dict)

def parse(self, response):
### The parse method is what is actually being repeated / iterated
for review in self.scrape_review(response):
yield review
# print(review)

# access next page of resturants
next_page_restaurants = response.xpath('//a[@class="nav next rndBtn ui_button primary taLnk"]/@href').extract_first()
next_page_restaurants_url = response.urljoin(next_page_restaurants)
yield Request(next_page_restaurants_url)
print(next_page_restaurants_url)

# access next page of reviews
next_page_reviews = response.xpath('//a[@class="nav next taLnk "]/@href').extract_first()
next_page_reviews_url = response.urljoin(next_page_reviews)
yield Request(next_page_reviews_url)
print(next_page_reviews_url)

# access each restaurant page:
url = response.xpath('//div[@id="EATERY_SEARCH_RESULTS"]/div/div/div/div/a[@target="_blank"]/@href').extract()
for url_next in url:
url_full = response.urljoin(url_next)
yield Request(url_full)

# "accesses the first review to get to the full reviews (not the truncated versions)"
first_review = response.xpath('//a[@class="title "]/@href').extract_first() # extract first used as I only want to access one of the links on this page to get down to "review level"
first_review_full = response.urljoin(first_review)
yield Request(first_review_full)
# print(first_review_full)










share|improve this question
























  • Can you post an actual link you're trying to scrape?

    – malberts
    Mar 23 at 14:28











  • Sure, my start URL is tripadvisor.co.uk/…

    – Dave C
    Mar 23 at 16:15













2












2








2








I am writing a spider to scrape a popular reviews website :-) This is my first attempt at writing a Scrapy spider.



The top level is a list of restaurants (I call this "top level"), which appear 30 at a time. My spider accesses each link and then "clicks next" to get the next 30, and so on. This part is working as my output does contain thousands of restaurants, not just the first 30.



I then want it to "click" on the link to each restaurant page ("restaurant level"), but this contains only truncated versions of the reviews, so I want it to then "click" down a further level (to "review level") and scrape the reviews from there, which appear 5 at a time with another "next" button. This is the only "level" from which I am extracting anything - the other levels just have links to access to get to the reviews and other info I want.



Most of this is working as I am getting all the information I want, but only for the first 5 reviews per restaurant. It is not "finding" the "next" button on the bottom "review level".



I have tried changing the order of commands within the parse method, but other than that I am coming up short of ideas! My xpaths are fine so it must be something to do with structure of the spider.



My spider looks thus:



import scrapy
from scrapy.http import Request

class TripSpider(scrapy.Spider):

name = 'tripadvisor'
allowed_domains = ['tripadvisor.co.uk']
start_urls = ['https://www.tripadvisor.co.uk/Restaurants-g187069-Manchester_Greater_Manchester_England.html']
custom_settings =
'DOWNLOAD_DELAY': 1,
# 'DEPTH_LIMIT': 3,
'AUTOTHROTTLE_TARGET_CONCURRENCY': 0.5,
'USER_AGENT': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
# 'DEPTH_PRIORITY': 1,
# 'SCHEDULER_DISK_QUEUE': 'scrapy.squeues.PickleFifoDiskQueue',
# 'SCHEDULER_MEMORY_QUEUE': 'scrapy.squeues.FifoMemoryQueue'


def scrape_review(self, response):
restaurant_name_review = response.xpath('//div[@class="wrap"]//span[@class="taLnk "]//text()').extract()
reviewer_name = response.xpath('//div[@class="username mo"]//text()').extract()
review_rating = response.xpath('//div[@class="wrap"]/div[@class="rating reviewItemInline"]/span[starts-with(@class,"ui_bubble_rating")]').extract()
review_title = response.xpath('//div[@class="wrap"]//span[@class="noQuotes"]//text()').extract()
full_reviews = response.xpath('//div[@class="wrap"]/div[@class="prw_rup prw_reviews_text_summary_hsx"]/div[@class="entry"]/p').extract()
review_date = response.xpath('//div[@class="prw_rup prw_reviews_stay_date_hsx"]/text()[not(parent::script)]').extract()
restaurant_name = response.xpath('//div[@id="listing_main_sur"]//a[@class="HEADING"]//text()').extract() * len(full_reviews)
restaurant_rating = response.xpath('//div[@class="userRating"]//@alt').extract() * len(full_reviews)
restaurant_review_count = response.xpath('//div[@class="userRating"]//a//text()').extract() * len(full_reviews)

for rvn, rvr, rvt, fr, rd, rn, rr, rvc in zip(reviewer_name, review_rating, review_title, full_reviews, review_date, restaurant_name, restaurant_rating, restaurant_review_count):
reviews_dict = dict(zip(['reviewer_name', 'review_rating', 'review_title', 'full_reviews', 'review_date', 'restaurant_name', 'restaurant_rating', 'restaurant_review_count'], (rvn, rvr, rvt, fr, rd, rn, rr, rvc)))
yield reviews_dict
# print(reviews_dict)

def parse(self, response):
### The parse method is what is actually being repeated / iterated
for review in self.scrape_review(response):
yield review
# print(review)

# access next page of resturants
next_page_restaurants = response.xpath('//a[@class="nav next rndBtn ui_button primary taLnk"]/@href').extract_first()
next_page_restaurants_url = response.urljoin(next_page_restaurants)
yield Request(next_page_restaurants_url)
print(next_page_restaurants_url)

# access next page of reviews
next_page_reviews = response.xpath('//a[@class="nav next taLnk "]/@href').extract_first()
next_page_reviews_url = response.urljoin(next_page_reviews)
yield Request(next_page_reviews_url)
print(next_page_reviews_url)

# access each restaurant page:
url = response.xpath('//div[@id="EATERY_SEARCH_RESULTS"]/div/div/div/div/a[@target="_blank"]/@href').extract()
for url_next in url:
url_full = response.urljoin(url_next)
yield Request(url_full)

# "accesses the first review to get to the full reviews (not the truncated versions)"
first_review = response.xpath('//a[@class="title "]/@href').extract_first() # extract first used as I only want to access one of the links on this page to get down to "review level"
first_review_full = response.urljoin(first_review)
yield Request(first_review_full)
# print(first_review_full)










share|improve this question
















I am writing a spider to scrape a popular reviews website :-) This is my first attempt at writing a Scrapy spider.



The top level is a list of restaurants (I call this "top level"), which appear 30 at a time. My spider accesses each link and then "clicks next" to get the next 30, and so on. This part is working as my output does contain thousands of restaurants, not just the first 30.



I then want it to "click" on the link to each restaurant page ("restaurant level"), but this contains only truncated versions of the reviews, so I want it to then "click" down a further level (to "review level") and scrape the reviews from there, which appear 5 at a time with another "next" button. This is the only "level" from which I am extracting anything - the other levels just have links to access to get to the reviews and other info I want.



Most of this is working as I am getting all the information I want, but only for the first 5 reviews per restaurant. It is not "finding" the "next" button on the bottom "review level".



I have tried changing the order of commands within the parse method, but other than that I am coming up short of ideas! My xpaths are fine so it must be something to do with structure of the spider.



My spider looks thus:



import scrapy
from scrapy.http import Request

class TripSpider(scrapy.Spider):

name = 'tripadvisor'
allowed_domains = ['tripadvisor.co.uk']
start_urls = ['https://www.tripadvisor.co.uk/Restaurants-g187069-Manchester_Greater_Manchester_England.html']
custom_settings =
'DOWNLOAD_DELAY': 1,
# 'DEPTH_LIMIT': 3,
'AUTOTHROTTLE_TARGET_CONCURRENCY': 0.5,
'USER_AGENT': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
# 'DEPTH_PRIORITY': 1,
# 'SCHEDULER_DISK_QUEUE': 'scrapy.squeues.PickleFifoDiskQueue',
# 'SCHEDULER_MEMORY_QUEUE': 'scrapy.squeues.FifoMemoryQueue'


def scrape_review(self, response):
restaurant_name_review = response.xpath('//div[@class="wrap"]//span[@class="taLnk "]//text()').extract()
reviewer_name = response.xpath('//div[@class="username mo"]//text()').extract()
review_rating = response.xpath('//div[@class="wrap"]/div[@class="rating reviewItemInline"]/span[starts-with(@class,"ui_bubble_rating")]').extract()
review_title = response.xpath('//div[@class="wrap"]//span[@class="noQuotes"]//text()').extract()
full_reviews = response.xpath('//div[@class="wrap"]/div[@class="prw_rup prw_reviews_text_summary_hsx"]/div[@class="entry"]/p').extract()
review_date = response.xpath('//div[@class="prw_rup prw_reviews_stay_date_hsx"]/text()[not(parent::script)]').extract()
restaurant_name = response.xpath('//div[@id="listing_main_sur"]//a[@class="HEADING"]//text()').extract() * len(full_reviews)
restaurant_rating = response.xpath('//div[@class="userRating"]//@alt').extract() * len(full_reviews)
restaurant_review_count = response.xpath('//div[@class="userRating"]//a//text()').extract() * len(full_reviews)

for rvn, rvr, rvt, fr, rd, rn, rr, rvc in zip(reviewer_name, review_rating, review_title, full_reviews, review_date, restaurant_name, restaurant_rating, restaurant_review_count):
reviews_dict = dict(zip(['reviewer_name', 'review_rating', 'review_title', 'full_reviews', 'review_date', 'restaurant_name', 'restaurant_rating', 'restaurant_review_count'], (rvn, rvr, rvt, fr, rd, rn, rr, rvc)))
yield reviews_dict
# print(reviews_dict)

def parse(self, response):
### The parse method is what is actually being repeated / iterated
for review in self.scrape_review(response):
yield review
# print(review)

# access next page of resturants
next_page_restaurants = response.xpath('//a[@class="nav next rndBtn ui_button primary taLnk"]/@href').extract_first()
next_page_restaurants_url = response.urljoin(next_page_restaurants)
yield Request(next_page_restaurants_url)
print(next_page_restaurants_url)

# access next page of reviews
next_page_reviews = response.xpath('//a[@class="nav next taLnk "]/@href').extract_first()
next_page_reviews_url = response.urljoin(next_page_reviews)
yield Request(next_page_reviews_url)
print(next_page_reviews_url)

# access each restaurant page:
url = response.xpath('//div[@id="EATERY_SEARCH_RESULTS"]/div/div/div/div/a[@target="_blank"]/@href').extract()
for url_next in url:
url_full = response.urljoin(url_next)
yield Request(url_full)

# "accesses the first review to get to the full reviews (not the truncated versions)"
first_review = response.xpath('//a[@class="title "]/@href').extract_first() # extract first used as I only want to access one of the links on this page to get down to "review level"
first_review_full = response.urljoin(first_review)
yield Request(first_review_full)
# print(first_review_full)







python-3.x scrapy






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 24 at 15:23







Dave C

















asked Mar 23 at 11:06









Dave CDave C

133




133












  • Can you post an actual link you're trying to scrape?

    – malberts
    Mar 23 at 14:28











  • Sure, my start URL is tripadvisor.co.uk/…

    – Dave C
    Mar 23 at 16:15

















  • Can you post an actual link you're trying to scrape?

    – malberts
    Mar 23 at 14:28











  • Sure, my start URL is tripadvisor.co.uk/…

    – Dave C
    Mar 23 at 16:15
















Can you post an actual link you're trying to scrape?

– malberts
Mar 23 at 14:28





Can you post an actual link you're trying to scrape?

– malberts
Mar 23 at 14:28













Sure, my start URL is tripadvisor.co.uk/…

– Dave C
Mar 23 at 16:15





Sure, my start URL is tripadvisor.co.uk/…

– Dave C
Mar 23 at 16:15












1 Answer
1






active

oldest

votes


















0














You are missing a space at the end of the class value:
enter image description here



Try this:



next_page_reviews = response.xpath('//a[@class="nav next taLnk "]/@href').extract_first()


Here are some tips on matching classes partially: https://docs.scrapy.org/en/latest/topics/selectors.html#when-querying-by-class-consider-using-css



On a side note, you can define separate parse functions to make it clearer what each one is responsible for: https://docs.scrapy.org/en/latest/intro/tutorial.html?highlight=callback#more-examples-and-patterns






share|improve this answer

























  • Thanks malberts. The page you are on is the restaurant page, which only contains partial reviews (if they are long). The spider should be going into one of the reviews on that page and scraping the reviews from reviews level, as they are complete there. The xpath I posted does match that next button. After I posted this yesterday I found callbacks and I thought that might help given the structure of the website, so I'm going to try and implement that today. Appreciate the pointers!

    – Dave C
    Mar 24 at 9:28












  • @DaveC Ah! I updated the answer. There seems to be an extra space in the class name.

    – malberts
    Mar 24 at 10:24












  • hmm that's odd... there is definitely a space there in my code so that isn't the problem unfortunately. The problem seems to be that when I print both "next page" url's to the console during execution, they come up the same. Even though both "next page" xpaths are correct. When I test the xpath for next_page_reviews in the Scrapy shell, it comes up with the correct url for the next page, but the script seems to be returning the next restaurants page url instead of the reviews one. So maybe the bug is in the line yield Request(next_page_reviews_url)? Should this be something else?

    – Dave C
    Mar 24 at 11:49












  • @DaveC Can you maybe post your full spider? I want to play around with it to see what happens.

    – malberts
    Mar 24 at 12:23











  • I seem to have made some progress and you might have been right about the missing space as it is now finding both next buttons. I am now getting reviews from several review-pages deep and across the first few pages of restaurants (it'll take a while to get to the later pages I guess as there are a lot of reviews!) The issue now is that it seems to be duplicating a lot of reviews in my output. I will amend the code in the main post to include the full spider so you can take a look if you don't mind. Thanks so much!

    – Dave C
    Mar 24 at 15:21











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55313045%2fscrapy-spider-finding-one-next-button-but-not-the-other%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














You are missing a space at the end of the class value:
enter image description here



Try this:



next_page_reviews = response.xpath('//a[@class="nav next taLnk "]/@href').extract_first()


Here are some tips on matching classes partially: https://docs.scrapy.org/en/latest/topics/selectors.html#when-querying-by-class-consider-using-css



On a side note, you can define separate parse functions to make it clearer what each one is responsible for: https://docs.scrapy.org/en/latest/intro/tutorial.html?highlight=callback#more-examples-and-patterns






share|improve this answer

























  • Thanks malberts. The page you are on is the restaurant page, which only contains partial reviews (if they are long). The spider should be going into one of the reviews on that page and scraping the reviews from reviews level, as they are complete there. The xpath I posted does match that next button. After I posted this yesterday I found callbacks and I thought that might help given the structure of the website, so I'm going to try and implement that today. Appreciate the pointers!

    – Dave C
    Mar 24 at 9:28












  • @DaveC Ah! I updated the answer. There seems to be an extra space in the class name.

    – malberts
    Mar 24 at 10:24












  • hmm that's odd... there is definitely a space there in my code so that isn't the problem unfortunately. The problem seems to be that when I print both "next page" url's to the console during execution, they come up the same. Even though both "next page" xpaths are correct. When I test the xpath for next_page_reviews in the Scrapy shell, it comes up with the correct url for the next page, but the script seems to be returning the next restaurants page url instead of the reviews one. So maybe the bug is in the line yield Request(next_page_reviews_url)? Should this be something else?

    – Dave C
    Mar 24 at 11:49












  • @DaveC Can you maybe post your full spider? I want to play around with it to see what happens.

    – malberts
    Mar 24 at 12:23











  • I seem to have made some progress and you might have been right about the missing space as it is now finding both next buttons. I am now getting reviews from several review-pages deep and across the first few pages of restaurants (it'll take a while to get to the later pages I guess as there are a lot of reviews!) The issue now is that it seems to be duplicating a lot of reviews in my output. I will amend the code in the main post to include the full spider so you can take a look if you don't mind. Thanks so much!

    – Dave C
    Mar 24 at 15:21















0














You are missing a space at the end of the class value:
enter image description here



Try this:



next_page_reviews = response.xpath('//a[@class="nav next taLnk "]/@href').extract_first()


Here are some tips on matching classes partially: https://docs.scrapy.org/en/latest/topics/selectors.html#when-querying-by-class-consider-using-css



On a side note, you can define separate parse functions to make it clearer what each one is responsible for: https://docs.scrapy.org/en/latest/intro/tutorial.html?highlight=callback#more-examples-and-patterns






share|improve this answer

























  • Thanks malberts. The page you are on is the restaurant page, which only contains partial reviews (if they are long). The spider should be going into one of the reviews on that page and scraping the reviews from reviews level, as they are complete there. The xpath I posted does match that next button. After I posted this yesterday I found callbacks and I thought that might help given the structure of the website, so I'm going to try and implement that today. Appreciate the pointers!

    – Dave C
    Mar 24 at 9:28












  • @DaveC Ah! I updated the answer. There seems to be an extra space in the class name.

    – malberts
    Mar 24 at 10:24












  • hmm that's odd... there is definitely a space there in my code so that isn't the problem unfortunately. The problem seems to be that when I print both "next page" url's to the console during execution, they come up the same. Even though both "next page" xpaths are correct. When I test the xpath for next_page_reviews in the Scrapy shell, it comes up with the correct url for the next page, but the script seems to be returning the next restaurants page url instead of the reviews one. So maybe the bug is in the line yield Request(next_page_reviews_url)? Should this be something else?

    – Dave C
    Mar 24 at 11:49












  • @DaveC Can you maybe post your full spider? I want to play around with it to see what happens.

    – malberts
    Mar 24 at 12:23











  • I seem to have made some progress and you might have been right about the missing space as it is now finding both next buttons. I am now getting reviews from several review-pages deep and across the first few pages of restaurants (it'll take a while to get to the later pages I guess as there are a lot of reviews!) The issue now is that it seems to be duplicating a lot of reviews in my output. I will amend the code in the main post to include the full spider so you can take a look if you don't mind. Thanks so much!

    – Dave C
    Mar 24 at 15:21













0












0








0







You are missing a space at the end of the class value:
enter image description here



Try this:



next_page_reviews = response.xpath('//a[@class="nav next taLnk "]/@href').extract_first()


Here are some tips on matching classes partially: https://docs.scrapy.org/en/latest/topics/selectors.html#when-querying-by-class-consider-using-css



On a side note, you can define separate parse functions to make it clearer what each one is responsible for: https://docs.scrapy.org/en/latest/intro/tutorial.html?highlight=callback#more-examples-and-patterns






share|improve this answer















You are missing a space at the end of the class value:
enter image description here



Try this:



next_page_reviews = response.xpath('//a[@class="nav next taLnk "]/@href').extract_first()


Here are some tips on matching classes partially: https://docs.scrapy.org/en/latest/topics/selectors.html#when-querying-by-class-consider-using-css



On a side note, you can define separate parse functions to make it clearer what each one is responsible for: https://docs.scrapy.org/en/latest/intro/tutorial.html?highlight=callback#more-examples-and-patterns







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 24 at 10:23

























answered Mar 24 at 8:47









malbertsmalberts

1,9391615




1,9391615












  • Thanks malberts. The page you are on is the restaurant page, which only contains partial reviews (if they are long). The spider should be going into one of the reviews on that page and scraping the reviews from reviews level, as they are complete there. The xpath I posted does match that next button. After I posted this yesterday I found callbacks and I thought that might help given the structure of the website, so I'm going to try and implement that today. Appreciate the pointers!

    – Dave C
    Mar 24 at 9:28












  • @DaveC Ah! I updated the answer. There seems to be an extra space in the class name.

    – malberts
    Mar 24 at 10:24












  • hmm that's odd... there is definitely a space there in my code so that isn't the problem unfortunately. The problem seems to be that when I print both "next page" url's to the console during execution, they come up the same. Even though both "next page" xpaths are correct. When I test the xpath for next_page_reviews in the Scrapy shell, it comes up with the correct url for the next page, but the script seems to be returning the next restaurants page url instead of the reviews one. So maybe the bug is in the line yield Request(next_page_reviews_url)? Should this be something else?

    – Dave C
    Mar 24 at 11:49












  • @DaveC Can you maybe post your full spider? I want to play around with it to see what happens.

    – malberts
    Mar 24 at 12:23











  • I seem to have made some progress and you might have been right about the missing space as it is now finding both next buttons. I am now getting reviews from several review-pages deep and across the first few pages of restaurants (it'll take a while to get to the later pages I guess as there are a lot of reviews!) The issue now is that it seems to be duplicating a lot of reviews in my output. I will amend the code in the main post to include the full spider so you can take a look if you don't mind. Thanks so much!

    – Dave C
    Mar 24 at 15:21

















  • Thanks malberts. The page you are on is the restaurant page, which only contains partial reviews (if they are long). The spider should be going into one of the reviews on that page and scraping the reviews from reviews level, as they are complete there. The xpath I posted does match that next button. After I posted this yesterday I found callbacks and I thought that might help given the structure of the website, so I'm going to try and implement that today. Appreciate the pointers!

    – Dave C
    Mar 24 at 9:28












  • @DaveC Ah! I updated the answer. There seems to be an extra space in the class name.

    – malberts
    Mar 24 at 10:24












  • hmm that's odd... there is definitely a space there in my code so that isn't the problem unfortunately. The problem seems to be that when I print both "next page" url's to the console during execution, they come up the same. Even though both "next page" xpaths are correct. When I test the xpath for next_page_reviews in the Scrapy shell, it comes up with the correct url for the next page, but the script seems to be returning the next restaurants page url instead of the reviews one. So maybe the bug is in the line yield Request(next_page_reviews_url)? Should this be something else?

    – Dave C
    Mar 24 at 11:49












  • @DaveC Can you maybe post your full spider? I want to play around with it to see what happens.

    – malberts
    Mar 24 at 12:23











  • I seem to have made some progress and you might have been right about the missing space as it is now finding both next buttons. I am now getting reviews from several review-pages deep and across the first few pages of restaurants (it'll take a while to get to the later pages I guess as there are a lot of reviews!) The issue now is that it seems to be duplicating a lot of reviews in my output. I will amend the code in the main post to include the full spider so you can take a look if you don't mind. Thanks so much!

    – Dave C
    Mar 24 at 15:21
















Thanks malberts. The page you are on is the restaurant page, which only contains partial reviews (if they are long). The spider should be going into one of the reviews on that page and scraping the reviews from reviews level, as they are complete there. The xpath I posted does match that next button. After I posted this yesterday I found callbacks and I thought that might help given the structure of the website, so I'm going to try and implement that today. Appreciate the pointers!

– Dave C
Mar 24 at 9:28






Thanks malberts. The page you are on is the restaurant page, which only contains partial reviews (if they are long). The spider should be going into one of the reviews on that page and scraping the reviews from reviews level, as they are complete there. The xpath I posted does match that next button. After I posted this yesterday I found callbacks and I thought that might help given the structure of the website, so I'm going to try and implement that today. Appreciate the pointers!

– Dave C
Mar 24 at 9:28














@DaveC Ah! I updated the answer. There seems to be an extra space in the class name.

– malberts
Mar 24 at 10:24






@DaveC Ah! I updated the answer. There seems to be an extra space in the class name.

– malberts
Mar 24 at 10:24














hmm that's odd... there is definitely a space there in my code so that isn't the problem unfortunately. The problem seems to be that when I print both "next page" url's to the console during execution, they come up the same. Even though both "next page" xpaths are correct. When I test the xpath for next_page_reviews in the Scrapy shell, it comes up with the correct url for the next page, but the script seems to be returning the next restaurants page url instead of the reviews one. So maybe the bug is in the line yield Request(next_page_reviews_url)? Should this be something else?

– Dave C
Mar 24 at 11:49






hmm that's odd... there is definitely a space there in my code so that isn't the problem unfortunately. The problem seems to be that when I print both "next page" url's to the console during execution, they come up the same. Even though both "next page" xpaths are correct. When I test the xpath for next_page_reviews in the Scrapy shell, it comes up with the correct url for the next page, but the script seems to be returning the next restaurants page url instead of the reviews one. So maybe the bug is in the line yield Request(next_page_reviews_url)? Should this be something else?

– Dave C
Mar 24 at 11:49














@DaveC Can you maybe post your full spider? I want to play around with it to see what happens.

– malberts
Mar 24 at 12:23





@DaveC Can you maybe post your full spider? I want to play around with it to see what happens.

– malberts
Mar 24 at 12:23













I seem to have made some progress and you might have been right about the missing space as it is now finding both next buttons. I am now getting reviews from several review-pages deep and across the first few pages of restaurants (it'll take a while to get to the later pages I guess as there are a lot of reviews!) The issue now is that it seems to be duplicating a lot of reviews in my output. I will amend the code in the main post to include the full spider so you can take a look if you don't mind. Thanks so much!

– Dave C
Mar 24 at 15:21





I seem to have made some progress and you might have been right about the missing space as it is now finding both next buttons. I am now getting reviews from several review-pages deep and across the first few pages of restaurants (it'll take a while to get to the later pages I guess as there are a lot of reviews!) The issue now is that it seems to be duplicating a lot of reviews in my output. I will amend the code in the main post to include the full spider so you can take a look if you don't mind. Thanks so much!

– Dave C
Mar 24 at 15:21



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55313045%2fscrapy-spider-finding-one-next-button-but-not-the-other%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript