Bevor wir unser Skript schreiben, überprüfen wir, ob die Installation von Puppeteer erfolgreich war:
import puppeteer from 'puppeteer';
async function scrapeYelpData(yelp_url: string): Promise<void> {
// Launch Puppeteer
const browser = await puppeteer.launch({
headless: false,
args: ['--start-maximized'],
defaultViewport: null
})
// Create a new page
const page = await browser.newPage()
// Navigate to the target URL
await page.goto(yelp_url)
// Close the browser
await browser.close()
}
scrapeYelpData("https://www.yelp.ie/biz/the-boxty-house-dublin?osq=Restaurants")
Hier öffnen wir ein Browserfenster, erstellen eine neue Seite, navigieren zu unserer Ziel-URL und schließen den Browser. Der Einfachheit und zur visuellen Fehlerbehebung halber öffne ich das Browserfenster im maximierten Modus im Nicht-Headless-Modus.
Schauen wir uns nun die Struktur der Website an:
Es scheint, dass Yelp eine etwas komplizierte Seitenstruktur aufweist, da die Klassennamen zufällig generiert werden und nur sehr wenige Elemente eindeutige Attributwerte haben.
Aber keine Sorge, wir können bei der Lösung kreativ werden. Um den Namen des Restaurants zu ermitteln, zielen wir zunächst auf das einzige „h1“-Element auf der Seite ab.
// Extract restaurant name
const restaurant_name = await page.evaluate(() => {
const name = document.querySelector('h1')
return name ? name.textContent : ''
})
console.log(restaurant_name)
Um nun die Restaurantbewertung zu erhalten, kannst du feststellen, dass neben den Sternsymbolen der explizite Wert im Attribut „aria-label“ vorhanden ist. Also zielen wir auf das „div“-Element ab, dessen „aria-label“-Attribut mit der Zeichenfolge „star rating“ endet.
// Extract restaurant rating
const restaurant_rating = await page.evaluate(() => {
const rating = document.querySelector('div[aria-label$="star rating"]')
return rating ? rating.getAttribute('aria-label') : ''
})
console.log(restaurant_rating)
Und schließlich (für diesen speziellen HTML-Abschnitt) sehen wir, dass wir die Anzahl der Bewertungen ganz einfach ermitteln können, indem wir das hervorgehobene Anker-Element ansprechen.
// Extract restaurant reviews
const restaurant_reviews = await page.evaluate(() => {
const reviews = document.querySelector('a[href="#reviews"]')
return reviews ? reviews.textContent : ''
})
console.log(restaurant_reviews)
Kinderleicht. Werfen wir einen Blick auf das Widget mit den Unternehmensinformationen:
Leider können wir uns in dieser Situation nicht auf CSS-Selektoren verlassen. Glücklicherweise können wir eine andere Methode nutzen, um die HTML-Elemente zu finden: XPath. Wenn du noch nicht so vertraut mit der Funktionsweise von CSS-Selektoren bist, schau dir gerne diesen Leitfaden für Anfänger an.
Um die Website des Restaurants zu extrahieren, wenden wir folgende Logik an:
Suchen Sie das „p“-Element, dessen Textinhalt „Business website“ lautet;
Suchen Sie das folgende Geschwisterelement
Suchen Sie das Anker-Element und dessen „href“-Attribut.
// Extract restaurant website
const restaurant_website_element = await page.$x("//p[contains(text(), 'Business website')]/following-sibling::p/a/@href")
const restaurant_website = await page.evaluate(
element => element.nodeValue,
restaurant_website_element[0]
)
console.log(restaurant_website)
Für die Telefonnummer und die Adresse können wir nun genau derselben Logik folgen, mit zwei Ausnahmen:
- Bei der Telefonnummer stoppen wir das nachfolgende Geschwisterelement und extrahieren dessen „textContent“-Eigenschaft;
- Für die Adresse zielen wir auf das nachfolgende Geschwisterelement des übergeordneten Elements ab.
// Extract restaurant phone number
const restaurant_phone_element = await page.$x("//p[contains(text(), 'Phone number')]/following-sibling::p")
const restaurant_phone = await page.evaluate(
element => element.textContent,
restaurant_phone_element[0]
)
console.log(restaurant_phone)
// Extract restaurant address
const restaurant_address_element = await page.$x("//a[contains(text(), 'Get Directions')]/parent::p/following-sibling::p")
const restaurant_address = await page.evaluate(
element => element.textContent,
restaurant_address_element[0]
)
console.log(restaurant_address)
Das Endergebnis sollte wie folgt aussehen:
The Boxty House
4.5 star rating
948 reviews
/biz_redir?url=http%3A%2F%2Fwww.boxtyhouse.ie%2F&cachebuster=1673542348&website_link_type=website&src_bizid=EoMjdtjMgm3sTv7dwmfHsg&s=16fbda8bbdc467c9f3896a2dcab12f2387c27793c70f0b739f349828e3eeecc3
(01) 677 2762
20-21 Temple Bar Dublin 2