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;
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
add a comment |
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
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
add a comment |
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
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
python-3.x scrapy
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
You are missing a space at the end of the class value:
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
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 lineyield 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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
You are missing a space at the end of the class value:
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
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 lineyield 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
add a comment |
You are missing a space at the end of the class value:
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
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 lineyield 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
add a comment |
You are missing a space at the end of the class value:
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
You are missing a space at the end of the class value:
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
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 lineyield 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
add a comment |
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 lineyield 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
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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