Bis hierhin haben wir einen funktionierenden Scraper. Aber das ist so ziemlich alles, was wir haben. Wenn du einen fortgeschritteneren Web-Scraper mit Pyppeteer erstellen möchtest, musst du id um weitere Funktionen erweitern. Spoiler-Alarm: Wir tauchen in die Welt der objektorientierten Programmierung ein. Aber zuerst wollen wir unsere Ziele festlegen. Was soll unser Scraper können?
- Den Browser mit einigen benutzerdefinierten Werten initialisieren
- Auf einer Webseite navigieren und Inhalte extrahieren
- Text in ein Eingabefeld schreiben
- Den Wert eines einzelnen Elements extrahieren
- Werte aus mehreren Elementen extrahieren
3.1. Benutzerdefinierte Optionen
Erstellen wir also zunächst eine neue `Scraper`-Klasse und fügen wir ihre Methoden später hinzu:
class Scraper:
def __init__(self, launch_options: dict) -> None:
self.options = launch_options['options']
self.viewPort = launch_options['viewPort'] if 'viewPort' in launch_options else None
pass
Das einzige Argument, das wir für unseren Scraper verwenden, ist ein `launch_options`-Wörterbuch. Wie du siehst, enthält es zwei Schlüssel. Ein Schlüssel definiert die Launcher-Optionen von Pyppeteer. Die zweite Option ist entweder `None` oder ein Wörterbuch, das die `width` und `height` des `viewPort` enthält. Letzteres wird für diese Methode verwendet.
3.2. Zu einer Seite navigieren
Wenn Sie sich die zuvor verwendete Funktion ansehen, werden Sie feststellen, dass wir sowohl die Navigation als auch das Extrahieren von Rohdaten aus einer bestimmten URL abdecken. Wir müssen die Funktion lediglich anpassen und in eine Methode für unseren Scraper umwandeln:
async def goto(self, url: str) -> None:
self.browser = await launch(options=self.options)
self.page = await self.browser.newPage()
await self.page.setViewport(self.viewPort) if self.viewPort != None else print('[i] Using default viewport')
await self.page.goto(url)
Diese Methode ist recht einfach. Zunächst startet sie einen neuen Browser mit den zuvor festgelegten benutzerdefinierten Optionen. Anschließend erstellt sie eine neue Seite und legt, sofern unser `launch_options`-Wörterbuch einen `viewPort` enthält, den ViewPort der Seite fest. Andernfalls protokolliert sie eine einfache Meldung. Zu guter Letzt führt sie uns zum Ziel.
3.3. Rohdaten aus einer Seite extrahieren
Auch hier haben wir die Methode in unserer ursprünglichen `scraper`-Funktion. Wir warten lediglich darauf, dass `page.content()` geladen wird, und geben dessen Wert zurück:
async def get_full_content(self) -> str:
content = await self.page.content()
return content
3.4. Text in ein Eingabefeld schreiben
Um mit Pyppeteer etwas in ein Eingabefeld zu schreiben, benötigen Sie zwei Dinge. Erstens: das Element lokalisieren. Zweitens: einen Wert hinzufügen. Glücklicherweise verfügt Pyppeteer über Methoden für beide Aktionen:
async def type_value(self, selector: str, value: str) -> None:
element = await self.page.querySelector(selector)
await element.type(value)
3.5. Wert aus einer Seite extrahieren
Denken Sie daran, dass wir entweder den Wert aus einem einzelnen Element oder Werte aus mehreren Elementen extrahieren wollen. Wir könnten für beides eine einzige Methode verwenden. Aber ich mag es normalerweise, wenn Dinge getrennt sind. Deshalb füge ich vorerst zwei weitere Methoden hinzu:
async def extract_one(self, selector) -> str:
element = await self.page.querySelector(selector)
text = await element.getProperty("textContent")
return await text.jsonValue()
Hier suchen wir das Element mithilfe der Methode `querySelector`. Anschließend warten wir auf den `textContent` und geben dessen `jsonValue()` zurück. Wenn wir hingegen mehrere Elemente auswählen möchten, verwenden wir `querySelector`:
async def extract_many(self, selector) -> list:
result = []
elements = await self.page.querySelectorAll(selector)
for element in elements:
text = await element.getProperty("textContent")
result.append(await text.jsonValue())
return result
Diese Methode funktioniert ähnlich wie `extract_one`. Der einzige Unterschied ist der Rückgabewert. Diesmal geben wir eine Liste aller Texte innerhalb der ausgewählten Elemente zurück. Und ich denke, mit dieser Ergänzung haben wir alle unsere Ziele erreicht.