Yelp is een van de grootste crowdsourced beoordelingsplatforms op internet. Met meer dan 200 miljoen beoordelingen van restaurants, bars, salons, winkels en andere bedrijven in meer dan 30 landen bevat het een goudmijn aan gegevens voor analisten, onderzoekers, ondernemers en meer.
Maar is het mogelijk om deze gegevens te extraheren via webscraping? Absoluut!
In deze uitgebreide gids van meer dan 3000 woorden deel ik alles wat je nodig hebt om een webschraper te bouwen die met Python enorme datasets uit Yelp kan extraheren.
Hier is een kort overzicht van wat we zullen behandelen:
- Het opzetten van onze Python webscraping-omgeving
- Het vinden en extraheren van alle bedrijven die aan een zoekopdracht voldoen
- Belangrijke details zoals naam, adres en telefoonnummers van bedrijfsprofielpagina's schrapen
- Het extraheren van alle beoordelingen voor een bedrijf, inclusief beoordelingen, gebruikersgegevens enz.
- Botdetectie vermijden via proxy's, vertragingen en andere trucs
Dus zet je schrap en laten we gaan schrapen!
Een Python Web Scraping-omgeving opzetten
Voordat we Yelp kunnen schrapen, moeten we een Python-omgeving opzetten met de vereiste afhankelijkheden.
Er zijn een paar belangrijke pakketten die we moeten installeren:
Aanvragen – om HTTP-verzoeken naar de servers van Yelp te sturen
Mooie soep – om gegevens uit de HTML-pagina's van Yelp te parseren en te extraheren
Scrapy – (optioneel) een raamwerk voor het bouwen van schrapers
Ik raad aan om een virtuele omgeving te maken voordat je deze installeert:
python -m venv scraping-env
source scraping-env/bin/activate
Nu kunnen we de pakketten installeren:
pip install requests beautifulsoup4 scrapy
Dat is het voor afhankelijkheden. We hebben ook geldige headers nodig, zodat de servers van Yelp denken dat onze verzoeken afkomstig zijn van een echte browser:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
}
De sleutel is het overtuigen User-Agent
koptekst. Ik raad aan om meerdere browsergebruikersagenten te roteren om echt verkeer verder na te bootsen.
En we zijn klaar om te beginnen met schrapen!
Bedrijven vinden op Yelp
Onze eerste uitdaging is het ontdekken van bedrijfsprofiel-URL's van Yelp die we kunnen scrapen. Yelp biedt geen openbare API of sitemap die we hiervoor kunnen opvragen.
We zullen dus hun zoekfunctionaliteit moeten reverse-engineeren om bedrijven te vinden die overeenkomen met een zoekterm of locatie.
Laten we een typische zoekopdracht analyseren:
https://www.yelp.com/search?find_desc=restaurants&find_loc=San+Francisco
Dit retourneert een gepagineerde reeks bedrijven die voldoen aan onze zoekcriteria. Elke pagina bevat 10 bedrijfsvermeldingen.
Om ALLE overeenkomende bedrijven te extraheren, moeten we:
- Haal de eerste pagina op om het totale aantal bedrijven te bekijken
- Blader door alle pagina's door de waarde te verhogen
start
parameter
Hier ziet u hoe we deze pagineringslogica in Python kunnen implementeren:
import requests
from urllib.parse import urlencode
from bs4 import BeautifulSoup
search_url = "https://www.yelp.com/search?"
params = {
"find_desc": "restaurants",
"find_loc": "San Francisco"
}
search_url += urlencode(params)
print("Fetching first page")
first_page = requests.get(search_url, headers=headers)
soup = BeautifulSoup(first_page.content, "html.parser")
businesses = soup.select(".businessName")
total = int(soup.select_one(".pagination-results-window").text.split()[0].replace(‘,‘, ‘‘))
print(f"Found {total} businesses")
# Calculate pages needed to cover all businesses
num_pages = math.ceil(total / 10)
print(f"Scraping {num_pages} pages...")
for page in range(0, num_pages):
# Update start param
params["start"] = page * 10
page_url = search_url + "&" + urlencode(params)
# Fetch page
print(f"Page {page+1}/{num_pages}")
page = requests.get(page_url, headers=headers)
# Extract businesses
page_soup = BeautifulSoup(page.content, "html.parser")
businesses.extend(page_soup.select(".businessName"))
print(f"Found {len(businesses)} businesses!")
Laten we dit opsplitsen:
- We beginnen met de basiszoek-URL en zoekparameters
- Haal de eerste pagina op om het totale aantal bedrijven te bekijken
- Bereken het aantal pagina's dat nodig is voor alle bedrijven
- Blader door de pagina's die het updaten
start
param - Op elke pagina extraheert u de bedrijfsvermeldingen en voegt u deze toe aan de hoofdlijst
In mijn test werd dit geëxtraheerd 6,000 restaurantvermeldingen in San Francisco – niet slecht voor 30 regels Python!
Met wat extra aanpassingen zou je er een zakelijke schraper van Yelp voor een hele stad of land van kunnen maken.
Bedrijfsprofielpagina's schrapen
Nu we bedrijfsprofiel-URL's kunnen ontdekken, is onze volgende stap het bezoeken van elke URL en het extraheren van belangrijke details, zoals:
- Naam
- Adres
- Telefoon
- Openingstijden
- Omschrijving
- Foto's
- En meer ...
De bedrijfspagina's van Yelp worden dynamisch weergegeven, maar de onderliggende HTML is eenvoudig genoeg om te parseren met BeautifulSoup.
Laten we een voorbeeldfragment bekijken:
<p>
<strong>Phone:</strong>
415-387-2147
</p>
<p>
<strong>Address:</strong>
1345 9th Ave, San Francisco, CA 94122
</p>
<!-- And so on... -->
We kunnen elk stukje informatie extraheren met een aantal goed geplaatste CSS-selectors:
from bs4 import BeautifulSoup
import requests
business_url = "https://www.yelp.com/biz/burma-superstar-san-francisco"
page = requests.get(business_url, headers=headers)
soup = BeautifulSoup(page.content, "html.parser")
name = soup.select_one("h1").text
phone = soup.find("strong", string="Phone:").next_sibling.strip()
address = soup.find("strong", string="Address:").next_sibling.strip()
hours = {}
for day in soup.select(".day-hours"):
day_name = day.select_one(".day-name").text
hours[day_name] = day.select_one(".hours").text
print(name)
print(phone)
print(address)
print(hours)
# Burma Superstar
# 415-387-2147
# 1345 9th Ave, San Francisco, CA 94122
# {‘Mon‘: ‘11:30am–3pm, 5–9:30pm‘, ‘Tue‘: ‘11:30am–3pm, 5–9:30pm‘...}
De belangrijkste punten zijn:
- Te gebruiken
select_one
om enkelvoudige elementen zoals naam, telefoon enz. te extraheren. - Voor geneste gegevens zoals uren, loop door en bouw een woordenboek
- Voeg aan CSS-selectors tags en klassen toe om ze uniek te maken
Met deze schrapende bouwstenen kunnen we tientallen velden van elke profielpagina extraheren naar een gestructureerd Python-woordenboek of JSON-object.
Enkele andere velden die u misschien wilt schrappen, zijn onder meer:
- Categorietags zoals 'Mexicaans', 'Brunch' etc.
- Keukentags zoals 'Burger', 'Sushi', 'Koffie' etc.
- COVID-veiligheidsmaatregelen
- Prijsbereik
- Buurt
- lengte-en breedtegraad
- En meer ...
Als u hier creatief aan de slag gaat, kunt u uitgebreide Yelp-datasets bouwen met honderden velden die u indien nodig kunt analyseren.
Reviews schrappen van Yelp-bedrijfspagina's
Recensies zijn de kroonjuwelen van de gegevens van Yelp. Ze bieden ongelooflijke inzichten in het consumentensentiment, trends, demografische gegevens en meer.
Helaas worden recensies niet rechtstreeks in de HTML geladen. Ze worden dynamisch opgehaald via JavaScript-aanroepen.
We moeten deze verzoeken onderscheppen en nabootsen om beoordelingsgegevens te extraheren.
Laten we een bedrijfspagina openen en netwerkverzoeken monitoren in de browsertools:
Aha – we kunnen zien dat beoordelingen worden geladen vanaf een URL zoals:
https://www.yelp.com/biz/{business_id}/reviews
Waar {business_id}
is uniek voor elk bedrijf. We kunnen het uit de HTML van de bedrijfspagina halen.
Recensies zijn gepagineerd via de start
parameter. We volgen dus dezelfde pagineringsstrategie:
- Haal de eerste pagina op om het totale aantal beoordelingen te bekijken
- Doorloop alle pagina's door te verhogen
start
Hier is een script om alle beoordelingen voor een bedrijf te extraheren:
import json
import requests
business_id = "WavvLdfdP6g8aZTtbBQHTw" # Extract this from HTML
review_url = f"https://www.yelp.com/biz/{business_id}/review_feed?rl=en&q=&sort_by=relevance_desc"
print("Fetching first page")
first_page = requests.get(review_url, headers=headers)
data = json.loads(first_page.text)
total = data["pagination"]["totalResults"]
print(f"Found {total} reviews")
reviews = data["reviews"]
for page in range(total//20 + 1): # 20 reviews per page
print(f"Fetching page {page+1}/{math.ceil(total/20)}")
next_page = f"{review_url}&start={page*20}"
page_data = requests.get(next_page, headers=headers).json()
reviews.extend(page_data["reviews"])
print(f"Scraped {len(reviews)} reviews!")
Boom! We hebben nu het volledige beoordelingscorpus voor een bedrijf met gegevens zoals:
{
"id": "xAG4O7l-t1ubiIsO4cXMYg",
"rating": 5,
"user": {
"id": "rpOyqD_893cqmDAtJLbdog",
"profile_url": "https://www.yelp.com/user_details?userid=rpOyqD_893cqmDAtJLbdog",
"name": "Sarah K.",
"location": "Los Angeles, CA",
//...
},
"text": "This place is incredible! The sushi melts in your mouth and the...",
//...
}
Het analyseren van deze gegevens kan sterke signalen opleveren over het klantsentiment op verschillende locaties, demografische gegevens, soorten keukens en meer.
Botdetectie vermijden
Nu we scrapers voor bedrijven en recensies hebben gebouwd, is het tijd om alles samen te voegen.
Eén probleem: als we de servers van Yelp belasten met duizenden verzoeken, worden we snel geblokkeerd.
Yelp maakt gebruik van geavanceerde botdetectiesystemen om misbruik te voorkomen, waaronder:
- Gebruikslimieten – beperk hoe snel u pagina's kunt opvragen
- CAPTCHA’s – daag gebruikers uit om te verifiëren dat ze een mens zijn
- IP-verboden – blokkeer onrechtmatige IP-adressen
Hier zijn enkele tips om blokkades te voorkomen terwijl je Yelp op grote schaal schrapt:
Gebruik proxy's
Door verkeer via een grote verzameling residentiële IP's te leiden, kunnen we scrapers maskeren en eenvoudige IP-verboden vermijden.
Hier ziet u hoe u proxy's kunt gebruiken met de module Verzoeken:
from proxy_list import proxies
# Rotate proxy per request
proxy = random.choice(proxies)
requests.get(url, headers=headers, proxies={"http": proxy, "https": proxy})
Ik zou aanraden om een zwembad te hebben tenminste 10,000 proxy's uit verschillende IP-bereiken om veilig te zijn.
Voeg willekeurige vertragingen toe
Door gevarieerde vertragingen tussen verzoeken toe te voegen, wordt organisch menselijk gedrag nagebootst:
from random import randint
# Add random delay between 2s and 6s
time.sleep(randint(2, 6))
Streef naar een gemiddelde van 3-5 seconden tussen pagina's. Sneller zal rode vlaggen oproepen.
Gebruik een headless browser
Voor meer anonimiteit kunt u een headless browser zoals Selenium gebruiken om JavaScript weer te geven en beveiligingen te omzeilen.
Zorg ervoor dat u de browservingerafdruk en proxy per sessie wijzigt.
Los CAPTCHA's op met 2Captcha
Als u toch een CAPTCHA tegenkomt, kunnen services zoals 2Captcha deze automatisch oplossen om door te gaan met schrapen.
De meeste diensten rekenen ongeveer $ 2 per 1000 opgeloste CAPTCHA's, wat de moeite waard is om grote schrapers te schalen.
Respecteer accountbeperkingen
Houd uw accountstatuspagina in de gaten. Als je scrape-percentage te agressief is, kan Yelp tijdelijke gebruikslimieten opleggen.
Houd uw verzoeken in de gaten en ga terug als fouten aangeven dat u een gebruiksdrempel nadert.
Yelp schrappen: volgende stappen
En dat omvat de kerntechnieken voor het verzamelen van bedrijfsvermeldingen, profielen en recensies van Yelp!
De gegevens die u kunt extraheren, bieden talloze mogelijkheden:
- Analyseer het consumentenvertrouwen in alle demografische categorieën
- Volg trends en opkomende soorten keukens
- Bouw voorspellende modellen voor zakelijke succesfactoren
- Optimaliseer uw eigen SEO en reputatie
- Voer een breed marktonderzoek uit
- Identificeer advertentiemogelijkheden
Vergeet niet om de Servicevoorwaarden van Yelp na te leven, het verzoekvolume te beperken en te voorkomen dat er privégebruikersgegevens worden opgehaald.
Ik hoop dat je deze handleiding nuttig vond! Neem gerust contact op als u nog vragen heeft.
Veel plezier met schrapen!