Home > Back-end >  Web Scraping using Python Beautiful Soup - how to scrape data from multiple pages if URL does not ch
Web Scraping using Python Beautiful Soup - how to scrape data from multiple pages if URL does not ch

Time:04-26

I am trying to extract customer reviews from: https://www.booking.com/hotel/sg/great-world-service-apartments.html#tab-reviews

The website currently has 6 pages containing reviews. Using beautiful soup and Selenium, I only managed to scrape the first page of reviews as the URL does not seem to change for each page. However, under request, the difference between each new page lies in the offset value ( 10 for each new page). For example,

page 1: https://www.booking.com/reviewlist.html?aid=304142&label=gen173nr-1FCAsoyQFCHmdyZWF0LXdvcmxkLXNlcnZpY2UtYXBhcnRtZW50c0gzWARoyQGIAQGYATG4ARfIAQzYAQHoAQH4AQKIAgGoAgO4AouUnZMGwAIB0gIkNDgwNDBjZjMtMjM2NS00MGQ2LTk5MzktY2NjZmFmYTZmZmVl2AIF4AIB&sid=ccc0bc594d1c5745616c91ebe852217f&cc1=sg&dist=1&pagename=great-world-service-apartments&type=total&offset=10&rows=10&_=1650936333328

page 2: https://www.booking.com/reviewlist.html?aid=304142&label=gen173nr-1FCAsoyQFCHmdyZWF0LXdvcmxkLXNlcnZpY2UtYXBhcnRtZW50c0gzWARoyQGIAQGYATG4ARfIAQzYAQHoAQH4AQKIAgGoAgO4AouUnZMGwAIB0gIkNDgwNDBjZjMtMjM2NS00MGQ2LTk5MzktY2NjZmFmYTZmZmVl2AIF4AIB&sid=ccc0bc594d1c5745616c91ebe852217f&cc1=sg&dist=1&pagename=great-world-service-apartments&type=total&**offset=20**&rows=10&_=1650936333332

page 3: https://www.booking.com/reviewlist.html?aid=304142&label=gen173nr-1FCAsoyQFCHmdyZWF0LXdvcmxkLXNlcnZpY2UtYXBhcnRtZW50c0gzWARoyQGIAQGYATG4ARfIAQzYAQHoAQH4AQKIAgGoAgO4AouUnZMGwAIB0gIkNDgwNDBjZjMtMjM2NS00MGQ2LTk5MzktY2NjZmFmYTZmZmVl2AIF4AIB&sid=ccc0bc594d1c5745616c91ebe852217f&cc1=sg&dist=1&pagename=great-world-service-apartments&type=total&offset=30&rows=10&_=1650936333335

page 4: https://www.booking.com/reviewlist.html?aid=304142&label=gen173nr-1FCAsoyQFCHmdyZWF0LXdvcmxkLXNlcnZpY2UtYXBhcnRtZW50c0gzWARoyQGIAQGYATG4ARfIAQzYAQHoAQH4AQKIAgGoAgO4AouUnZMGwAIB0gIkNDgwNDBjZjMtMjM2NS00MGQ2LTk5MzktY2NjZmFmYTZmZmVl2AIF4AIB&sid=ccc0bc594d1c5745616c91ebe852217f&cc1=sg&dist=1&pagename=great-world-service-apartments&type=total&offset=40&rows=10&_=1650936333338

So far, I found the page number list too as attached below (Under Inspect). Would it be advisable to make use of page number list or the difference in offset values to perform the scraping for the rest of the pages?

enter image description here

My current codes are as follows:

import scrapy
import pandas as pd
import numpy as np
import re
import requests
import bs4
from bs4 import BeautifulSoup
import csv

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

#Install driver
driver = webdriver.Chrome('./chromedriver.exe') 

#specify URL
url1 = 'https://www.booking.com/hotel/sg/great-world-service-apartments.html#tab-reviews'
driver.get(url1) 
time.sleep(5) 
html = driver.page_source

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36'}

r= requests.get(url1,{'headers':headers})
soup = bs4.BeautifulSoup(r.text,'html.parser')
title = soup.head.title 
print(title)
print(list(soup.children))
print(list(soup.parents))
titleparent = soup.title.parent.name
print(titleparent)


#Get all reviews
from selenium.webdriver.common.by import By
reviews = driver.find_element(by=By.CLASS_NAME, value='review_list_new_item_block')
print(reviews)
#reviews = soup.find(class_='review_list')
#title = reviews['title']
#reviews = soup.find_all('ul',class_='review_list')
#print(title)

#Find attributes
#1) Customer Name
names = soup.find_all('span',class_='bui-avatar-block__title')
#print(names)

cust_names = []
for i in range(0,len(names)):
    cust_names.append(names[i].get_text())
    
cust_names = cust_names[:10]
print(cust_names)

#2) Country
country = soup.find_all('span',class_='bui-avatar-block__subtitle')
#print(country) 
country_list = []
for i in range(0,len(country)):
    country_list.append(country[i].get_text())
country_list[:] = [country.strip('\n') for country in country_list]
country_list = country_list[:10]
print(country_list)

#3) Header
header = soup.find_all('div',string=lambda text:"bui-grid__column-9 c-review-block__right")
#print(header)

headers_list = []
for i in range(0,len(header)):
    headers_list.append(header[i].get_text())
headers_list[:] = [header.strip('\n') for header in headers_list]
headers_list = headers_list[:10]
#print(headers_list)

#4) Positive Reviews
positive_reviews = soup.find_all('span',{'class':'c-review__body'},{'svg':'bk-icon -iconset-review_great c-review__icon'})
#print(positive_reviews)

pos_reviews_list = []
for i in range(0,len(positive_reviews)):
    pos_reviews_list.append(positive_reviews[i].get_text())
#pos_reviews_list[:] = [positive_reviews.strip('\n') for positive_reviews in pos_reviews_list]
print(pos_reviews_list)


#Store into a dataframe
data = {'Customer Name': cust_names,
        'Country': country_list,'Positive Reviews':pos_reviews_list}

GWSAReviews1 = pd.DataFrame(data=data)
print(GWSAReviews1)

#GWSAReviews1.to_csv('GWSAReviews1.csv')

Would appreciate if someone can help me on this, thank you in advance!

CodePudding user response:

I cannot add comment as i dont have enough reputations. but i believe its not only the offset which is changing, the other part of url is also changing

=1650936333328
=1650936333332
=1650936333338

please check if this affects the way you want to write code, its just an observation and suggestion.

CodePudding user response:

There is no problem with your URLs , you can use them and you can limited page number list to solve your problem as mentioned

  • Related