Wir haben nur die ersten 10 Währungen gescrapt, da CoinMarketCap beim ersten Laden der Seite nur so viele lädt. Um mehr zu scrapen, müssen wir eine menschliche Aktion ausführen, nämlich das Scrollen der Seite. Glücklicherweise eignet sich Playwright gut für diese Aufgabe.
Beginnen wir damit, die zuvor verwendete $$eval-Funktion umzugestalten und eine Paginierung zu implementieren. Wir nennen diese neue Funktion extractData:
const extractData = async (page, currentPage, perPage = 10) => {
}
Wir erweitern den :nth-child-Selektor, indem wir Elemente schrittweise auswählen (Elemente von 0 bis 10, von 11 bis 21, von 22 bis 32 usw.). Wir definieren den anfänglichen Selektor (die ersten 10 Elemente):
let selector = `:nth-child(-n+${currentPage * perPage})`;
Zu guter Letzt fügen wir Unterstützung für die nächsten Seiten hinzu. Der Code sieht wie folgt aus:
if(currentPage > 1) {
selector = `:nth-child(n+${(currentPage - 1) + perPage}):nth-child(-n+${(currentPage * perPage) + 1})`;
}
Die endgültige Funktion sieht wie folgt aus:
const extractData = async (page, currentPage, perPage = 10) => {
let selector = `:nth-child(-n+${currentPage * perPage})`;
if(currentPage > 1) {
selector = `:nth-child(n+${(currentPage - 1) + perPage}):nth-child(-n+${(currentPage * perPage) + 1})`;
}
return await page.$$eval(`.cmc-table tbody tr${selector}`, trs => {
const data = [];
trs.forEach(tr => {
data.push({
name: tr.querySelector('td:nth-child(3) a .name-area p').innerHTML,
price: tr.querySelector('td:nth-child(4) a span').innerHTML,
});
});
return data;
});
};
Nun ist es an der Zeit, zu unserem Scraper-Code zurückzukehren, das Scrollen zu implementieren und die Datenextraktion zu erweitern. Wir führen alle Arbeiten nach dieser Zeile durch:
await page.goto('https://coinmarketcap.com');
Wir definieren die Variable „currencies“ neu:
// Extract the currencies data
let currencies = await extractData(page, 1, 10);
Mit der Funktion „evaluate“ scrollen wir die Seite auf das 1,5-fache des Viewports. Dadurch werden die nächsten Elemente der Tabelle geladen:
// Scroll the page to a little more than the viewport height
await page.evaluate(() => {
window.scrollTo(0, window.innerHeight * 1.5);
});
Die Wartezeit von einer Sekunde gibt der Benutzeroberfläche etwas Zeit, die Tabelle mit den von der API abgerufenen Daten zu füllen:
// Wait for the new elements to load
await page.waitForTimeout(1000);
Zuletzt extrahieren wir die Daten von der zweiten Seite und protokollieren die Ergebnisse:
// Extract the next 10 elements
currencies = [...currencies, ...await extractData(page, 2, 10)]
// Display the results
console.log(currencies)
Der vollständige Code für den Scraper sollte wie folgt aussehen:
const { chromium } = require('playwright');
const extractData = async (page, currentPage, perPage = 10) => {
let selector = `:nth-child(-n+${currentPage * perPage})`;
if(currentPage > 1) {
selector = `:nth-child(n+${(currentPage - 1) + perPage}):nth-child(-n+${(currentPage * perPage) + 1})`;
}
return await page.$$eval(`.cmc-table tbody tr${selector}`, trs => {
const data = [];
trs.forEach(tr => {
data.push({
name: tr.querySelector('td:nth-child(3) a .name-area p').innerHTML,
price: tr.querySelector('td:nth-child(4) a span').innerHTML,
});
})
return data;
})
};
(async () => {
// Launch a Chromium browser
const browser = await chromium.launch();
// Create a new page in the browser
const page = await browser.newPage();
// Navigate to a website
await page.goto('https://coinmarketcap.com');
// Extract the currencies data
let currencies = await extractData(page, 1, 10)
// Scroll the page to a little more than the viewport height
await page.evaluate(() => {
window.scrollTo(0, window.innerHeight * 1.5);
});
// Wait for the new elements to load
await page.waitForTimeout(1000);
// Extract the next 10 elements
currencies = [...currencies, ...await extractData(page, 2, 10)];
// Display the results
console.log(currencies);
// Close the browser
await browser.close();
})();
Zusammenfassend lässt sich sagen, dass der Scraper die CoinMarketCap-Startseite öffnet, die Daten der ersten 10 Währungen extrahiert, die Seite scrollt, die Daten der nächsten 10 Währungen extrahiert und die Ergebnisse anzeigt.
Sie sollten ähnliche Ergebnisse wie diese erhalten:
[
{ name: 'Bitcoin', price: '$16,742.58' },
{ name: 'Ethereum', price: '$1,244.45' },
{ name: 'Tether', price: '$0.9997' },
{ name: 'USD Coin', price: '$1.00' },
{ name: 'BNB', price: '$255.78' },
{ name: 'XRP', price: '$0.335' },
{ name: 'Binance USD', price: '$1.00' },
{ name: 'Dogecoin', price: '$0.07066' },
{ name: 'Cardano', price: '$0.2692' },
{ name: 'Polygon', price: '$0.7762' },
{ name: 'Dai', price: '$0.9994' },
{ name: 'Litecoin', price: '$73.80' },
{ name: 'Polkadot', price: '$4.59' },
{ name: 'Solana', price: '$12.95' },
{ name: 'TRON', price: '$0.0505' },
{ name: 'Shiba Inu', price: '$0.000008234' },
{ name: 'Uniswap', price: '$5.29' },
{ name: 'Avalanche', price: '$11.43' },
{ name: 'UNUS SED LEO', price: '$3.47' },
{ name: 'Wrapped Bitcoin', price: '$16,725.03' },
{ name: 'Cosmos', price: '$9.97' }
]