Beheer van Chrome (puppeteer)

A-Parser maakt het mogelijk om de Chrome (Chromium) browser te gebruiken als engine voor het downloaden en renderen van pagina's, gebruikmakend van de populaire bibliotheek puppeteer.
De belangrijkste voordelen van het gebruik van puppeteer in combinatie met A-Parser:
- ondersteuning voor afzonderlijke proxy's voor elk browsertabblad
- multithreading beheer van browsertabbladen
- onderscheppen van verzoeken
- alle mogelijkheden van A-Parser voor wachtrijbeheer, het vormen van verzoeken en het verwerken van resultaten
Het gebruik van de Chrome browser biedt de volgende mogelijkheden:
- rendering van
DOMenJavaScript - mogelijkheid tot interactie met website-elementen:
- invullen van formulieren
- klikken op links
- drag & drop
- uploaden van bestanden
- muisemulatie
- en nog veel meer, alle standaardacties kunnen worden geautomatiseerd
- eenvoudiger omzeilen van diverse anti-scraping beveiligingen, aangezien de Chromium-browser maximaal lijkt op de browser die door gebruikers wordt gebruikt
- mogelijkheid om in
Headlessmodus te werken, d.w.z. zonder grafische interface van de browser, wat resources bespaart en het mogelijk maakt de browser op servers zonder grafische omgeving te draaien
Houd er rekening mee dat het gebruik van een browser veel veeleisender is voor resources (CPU, geheugen) dan normale A-Parser threads.
Afhankelijk van de complexiteit van de website wordt aanbevolen om niet meer dan 1-2 threads (browsertabbladen) per beschikbare processorkern te gebruiken, bijvoorbeeld voor 8-core processors - van 8 tot 16 tabbladen.
Voorbeeld van gebruik
Laten we kijken naar het voorbeeld van de scraper Chrome::ScreenshotMaker2:
- de scraper maakt screenshots van websites op het opgegeven formaat en kan de afbeelding ook verkleinen (schalen)
- kan optioneel proxy's gebruiken
- maakt een apart browsertabblad aan voor elke A-Parser thread
import { BaseParser, PuppeteerTypes } from 'a-parser-types';
let browser: PuppeteerTypes.Browser;
let jimp;
class JS_Chrome_ScreenshotsMaker2 extends BaseParser {
static defaultConf: typeof BaseParser.defaultConf = {
version: '0.2.1',
results: {
flat: [
['screenshot', 'PNG screenshot'],
]
},
results_format: '$screenshot',
load_timeout: 30,
width: 1024,
height: 768,
log_screenshots: 0,
headless: 1,
};
static editableConf: typeof BaseParser.editableConf = [
['log_screenshots', ['checkbox', 'Log Screenshots']],
['width', ['textfield', 'Viewport Width']],
['height', ['textfield', 'Viewport Height']],
['resize_width', ['textfield', 'Resize Width']],
['resize_height', ['textfield', 'Resize Height']],
['headless', ['checkbox', 'Chrome Headless']],
];
async init() {
// initialiseer de browser
browser = await this.puppeteer.launch({
headless: this.conf.headless,
logConnections: false,
defaultViewport: {
width: parseInt(this.conf.width),
height: parseInt(this.conf.height),
}
});
if (this.conf.resize_width) {
// sluit de jimp-module aan als het nodig is om de screenshot te resizen
jimp = require('jimp');
};
};
async destroy() {
// sluit de browser na voltooiing van de taak
if (browser)
await browser.close();
}
page: PuppeteerTypes.Page;
async threadInit() {
// maak een browserpagina aan bij de initialisatie van de thread
this.page = await browser.newPage();
// standaard puppeteer-methoden
await this.page.setCacheEnabled(true);
await this.page.setDefaultNavigationTimeout(this.conf.timeout * 1000);
// geef A-Parser de opdracht om een proxy te gebruiken voor deze pagina
await this.puppeteer.setPageUseProxy(this.page);
this.logger.put(`New page created for thread #${this.threadId}`);
}
async parse(set, results) {
const self = this;
const { conf, page } = self;
for (let attempt = 1; attempt <= conf.proxyretries; attempt++) {
try {
self.logger.put(`Attempt #${attempt}`);
// ga naar de pagina die in het verzoek is opgegeven
await page.goto(set.query);
// verberg de scrollbar voor de screenshot
await page.evaluate(() => { document.querySelector('html').style.overflow = 'hidden'; });
// maak screenshot
results.screenshot = await page.screenshot();
if (parseInt(conf.resize_width)) {
// resize de afbeelding indien nodig
let image = await jimp.read(results.screenshot);
image.resize(parseInt(conf.resize_width), parseInt(conf.resize_height));
results.screenshot = await image.getBufferAsync('image/png');
}
self.logger.put(`Screenshot(${attempt}): OK, size: ${parseInt("" + (results.screenshot.length / 1024))}KB`);
if (conf.log_screenshots)
self.logger.putHTML("<img src='data:image/png;base64," + results.screenshot.toString('base64') + "'>");
results.success = 1;
// sluit huidige verbindingen omdat de browser keep-alive gebruikt
await self.puppeteer.closeActiveConnections();
break;
}
catch (error) {
self.logger.put(`Fetch page error: ${error}`);
// sluit huidige verbindingen omdat de browser keep-alive gebruikt
await self.puppeteer.closeActiveConnections();
// wissel van proxy voor het browsertabblad
await self.proxy.next();
}
}
return results;
}
}
Dit voorbeeld demonstreert de eenvoud van het gebruik van verschillende proxy's voor elk tabblad, evenals multithreading (1 thread = 1 browsertabblad).
Beschrijving van methoden
await this.puppeteer.launch(opts?)
Deze methode is vergelijkbaar met de .launch methode van de puppeteer bibliotheek; het start de Chromium browser met de benodigde opties opts. Het belangrijkste verschil is de integratie met A-Parser en ondersteuning voor proxy's per tabblad, evenals de beschikbaarheid van extra opties:
logConnections?: boolean
Schakelt logging in voor alle verbindingen (ongeacht of er een proxy wordt gebruikt of niet), de log-output wordt per thread gescheiden weergegeven.
stealth?: boolean
Gebruikt de plugin puppeteer-extra om Chromium te camoufleren als een echte Chrome.
stealthOpts?: any
Extra opties voor de puppeteer-extra plugin.
extraPlugins?: array
Gebruik van extra plugins, zoals bijvoorbeeld puppeteer-extra/packages.

Overige opties
Alle overige startopties zijn te vinden in de originele documentatie van puppeteer.
await this.puppeteer.setPageUseProxy(page)
Deze methode koppelt de browserpagina aan de A-Parser thread voor een correcte werking van de proxy; deze moet direct na het aanmaken van de pagina worden aangeroepen:
const page = await browser.newPage();
await this.puppeteer.setPageUseProxy(page);
await this.puppeteer.closeActiveConnections(page?)
Deze methode moet worden aangeroepen na voltooiing van de verwerking van het verzoek of voordat de proxy wordt gewisseld voor de volgende poging.
De Chrome browser laat standaard verbindingen openstaan met de websites waarmee verbinding is gemaakt; deze methode maakt het mogelijk om het aantal gebruikte resources te controleren en vermindert de belasting op de proxy.
Het argument page is optioneel; bij aanroep zonder argument zal A-Parser de verbindingen sluiten voor het tabblad dat aan de huidige thread is gekoppeld.
await this.puppeteer.logScreenshot()
De methode logt een screenshot van de huidige pagina.