Yelp è una delle più grandi piattaforme di recensioni di crowdsourcing sul web. Con oltre 200 milioni di recensioni di ristoranti, bar, saloni, negozi e altre attività commerciali in oltre 30 paesi, contiene una miniera d'oro di dati per analisti, ricercatori, imprenditori e altro ancora.
Ma è possibile estrarre questi dati tramite web scraping? Assolutamente!
In questa guida completa di oltre 3000 parole, condividerò tutto ciò di cui hai bisogno per creare un web scraper in grado di estrarre enormi set di dati da Yelp utilizzando Python.
Ecco una breve descrizione di ciò che tratteremo:
- Configurazione del nostro ambiente di web scraping Python
- Trovare ed estrarre tutte le attività commerciali che corrispondono a una query di ricerca
- Eliminazione di dettagli chiave come nome, indirizzo, numeri di telefono dalle pagine del profilo aziendale
- Estrazione di tutte le recensioni per un'azienda, comprese valutazioni, dettagli utente, ecc.
- Evitare il rilevamento dei bot tramite proxy, ritardi e altri trucchi
Quindi allacciatevi le cinture e cominciamo a raschiare!
Configurazione di un ambiente di web scraping Python
Prima di poter scaricare Yelp, dobbiamo configurare un ambiente Python con le dipendenze richieste.
Ci sono alcuni pacchetti chiave che dobbiamo installare:
Richieste – per inviare richieste HTTP ai server di Yelp
bellazuppa – per analizzare ed estrarre dati dalle pagine HTML di Yelp
Scrapy – (opzionale) una struttura per la costruzione di raschiatori
Consiglierei di creare un ambiente virtuale prima di installare questi:
python -m venv scraping-env
source scraping-env/bin/activate
Ora possiamo installare i pacchetti:
pip install requests beautifulsoup4 scrapy
Questo è tutto per le dipendenze. Abbiamo anche bisogno di intestazioni valide in modo che i server di Yelp pensino che le nostre richieste provengano da un browser reale:
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"
}
La chiave è convincere User-Agent
intestazione. Consiglierei di ruotare più user agent del browser per imitare ulteriormente il traffico reale.
E siamo pronti per iniziare a raschiare!
Trovare attività commerciali su Yelp
La nostra prima sfida è scoprire gli URL dei profili aziendali di Yelp da recuperare. Yelp non fornisce un'API pubblica o una mappa del sito su cui possiamo eseguire query a questo scopo.
Quindi dovremo decodificare la loro funzionalità di ricerca per trovare attività commerciali che corrispondono a un termine di ricerca o a una posizione.
Analizziamo una tipica query di ricerca:
https://www.yelp.com/search?find_desc=restaurants&find_loc=San+Francisco
Ciò restituisce un insieme impaginato di attività commerciali che corrispondono ai nostri criteri di ricerca. Ogni pagina contiene 10 elenchi di attività commerciali.
Per estrarre TUTTE le attività commerciali corrispondenti, dobbiamo:
- Recupera la prima pagina per ottenere il conteggio totale delle attività
- Scorrere tutte le pagine incrementando il file
start
parametro
Ecco come possiamo implementare questa logica di impaginazione in Python:
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!")
Analizziamolo:
- Iniziamo con l'URL di ricerca di base e i parametri di ricerca
- Recupera la prima pagina per ottenere il conteggio totale delle attività
- Calcola il numero di pagine necessarie per coprire tutte le attività
- Scorri le pagine aggiornando il file
start
param - In ogni pagina, estrai elenchi di attività commerciali e aggiungili all'elenco principale
Nel mio test questo è stato estratto 6,000 elenchi di ristoranti a San Francisco – non male per 30 righe di Python!
Con alcune modifiche extra potresti trasformarlo in un business scraper di Yelp per un'intera città o paese.
Raschiare le pagine del profilo aziendale
Ora che possiamo scoprire gli URL dei profili aziendali, il nostro prossimo passo è visitare ciascuno di essi ed estrarre dettagli chiave come:
- Nome
- Indirizzo
- Numero di telefono
- Orari di apertura
- Descrizione
- Foto
- E altre ancora...
Le pagine aziendali di Yelp vengono visualizzate in modo dinamico, ma l'HTML sottostante è abbastanza semplice da essere analizzato con BeautifulSoup.
Diamo un'occhiata a uno snippet di esempio:
<p>
<strong>Phone:</strong>
415-387-2147
</p>
<p>
<strong>Address:</strong>
1345 9th Ave, San Francisco, CA 94122
</p>
<!-- And so on... -->
Possiamo estrarre ogni bit di informazione con alcuni selettori CSS ben posizionati:
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‘...}
I punti chiave sono:
- Usa il
select_one
per estrarre elementi singolari come nome, telefono ecc. - Per i dati nidificati come le ore, esegui il loop e crea un dizionario
- Prefisso i selettori CSS con tag e classi per unicità
Con questi elementi costitutivi di scraping, possiamo estrarre dozzine di campi da ciascuna pagina del profilo in un dizionario Python strutturato o un oggetto JSON.
Alcuni altri campi che potresti prendere in considerazione per lo scraping includono:
- Tag di categoria come "Messicano", "Brunch" ecc.
- Tag di cucina come "Burger", "Sushi", "Caffè" ecc.
- Misure di sicurezza COVID
- Prezzo
- quartiere
- latitudine Longitudine
- E altre ancora...
Essere creativi qui ti consente di creare ampi set di dati Yelp con centinaia di campi da analizzare se necessario.
Rimozione di recensioni dalle pagine aziendali di Yelp
Le recensioni sono il fiore all'occhiello dei dati di Yelp. Forniscono informazioni incredibili sul sentiment dei consumatori, sulle tendenze, sui dati demografici e altro ancora.
Sfortunatamente, le recensioni non vengono caricate direttamente nell'HTML. Vengono recuperati dinamicamente tramite chiamate JavaScript.
Dovremo intercettare e imitare queste richieste per estrarre i dati delle recensioni.
Apriamo una pagina aziendale e monitoriamo le richieste di rete negli strumenti del browser:
Aha – possiamo vedere che le recensioni vengono caricate da un URL come:
https://www.yelp.com/biz/{business_id}/reviews
Dove {business_id}
è unico per ogni azienda. Possiamo estrarlo dall'HTML della pagina aziendale.
Le recensioni vengono impaginate tramite il file start
parametro. Quindi seguiremo la stessa strategia di impaginazione:
- Recupera la prima pagina per ottenere il conteggio totale delle recensioni
- Scorrere tutte le pagine incrementando
start
Ecco uno script per estrarre tutte le recensioni per un'azienda:
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! Ora disponiamo del corpus completo delle recensioni di un'azienda con dati quali:
{
"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...",
//...
}
L'analisi di questi dati può fornire segnali forti sul sentiment dei clienti in base a località, dati demografici, tipi di cucina e altro ancora.
Evitare il rilevamento dei bot
Ora che abbiamo creato scraper per aziende e recensioni, è il momento di mettere tutto insieme.
Un problema: se iniziamo a intasare i server di Yelp con migliaia di richieste, verremo rapidamente bloccati.
Yelp utilizza sistemi avanzati di rilevamento dei bot per prevenire gli abusi, tra cui:
- Limiti di utilizzo: limita la velocità con cui puoi richiedere le pagine
- CAPTCHA: sfidano gli utenti a verificare che siano umani
- Divieti IP: blocca gli indirizzi IP offensivi
Ecco alcuni suggerimenti per evitare blocchi durante lo scraping di Yelp su larga scala:
Usa i proxy
Instradando il traffico attraverso un ampio pool di IP residenziali, possiamo mascherare gli scraper ed evitare facili ban degli IP.
Ecco come utilizzare i proxy con il modulo Richieste:
from proxy_list import proxies
# Rotate proxy per request
proxy = random.choice(proxies)
requests.get(url, headers=headers, proxies={"http": proxy, "https": proxy})
Consiglierei di avere una piscina almeno 10,000 proxy provenienti da diversi intervalli IP per essere sicuri.
Aggiungi ritardi casuali
L'aggiunta di vari ritardi tra le richieste aiuta a imitare il comportamento umano organico:
from random import randint
# Add random delay between 2s and 6s
time.sleep(randint(2, 6))
Punta a una media di secondi 3-5 tra le pagine. Qualsiasi velocità più veloce farà alzare le bandiere rosse.
Utilizza un browser senza testa
Per un maggiore anonimato, puoi utilizzare un browser headless come Selenium per eseguire il rendering di JavaScript e aggirare le protezioni.
Assicurati solo di modificare l'impronta digitale del browser e il proxy per sessione.
Risolvi i CAPTCHA con 2Captcha
Se colpisci un CAPTCHA, servizi come 2Captcha possono risolverli automaticamente per continuare lo scraping.
La maggior parte dei servizi addebita circa $ 2 per 1000 CAPTCHA risolti, il che vale la pena scalare grandi scraper.
Rispettare le limitazioni dell'account
Tieni d'occhio la pagina di stato del tuo account. Se il tuo tasso di scraping è troppo aggressivo, Yelp potrebbe imporre limiti di utilizzo temporanei.
Riduci le tue richieste e fai marcia indietro se gli errori indicano che ti stai avvicinando a una soglia di utilizzo.
Scraping Yelp: passaggi successivi
E questo copre le tecniche di base per lo scraping degli elenchi di attività commerciali, dei profili e delle recensioni di Yelp!
I dati che puoi estrarre aprono tantissime possibilità:
- Analizzare il sentiment dei consumatori in base ai dati demografici
- Tieni traccia delle tendenze e dei tipi di cucina emergenti
- Costruisci modelli predittivi per i fattori di successo aziendale
- Ottimizza il tuo SEO e la tua reputazione
- Condurre ampie ricerche di mercato
- Identificare le opportunità pubblicitarie
Ricorda solo di rispettare i Termini di servizio di Yelp, limitare il volume delle richieste ed evitare di estrarre dati privati degli utenti.
Spero che questa guida ti sia stata utile! Sentiti libero di contattarci se hai altre domande.
Buona raschiatura!