Meteen naar de inhoud

Hoe verborgen webgegevens te schrapen

Het verzamelen van gegevens van het moderne internet kan vaak aanvoelen als een spelletje verstoppertje. Terwijl tien jaar geleden de meeste informatie direct beschikbaar was in HTML, houden ontwikkelaars er tegenwoordig van om gegevens te verbergen en te verdoezelen, en deze dynamisch weer te geven met JavaScript.

Dit vormt een interessante uitdaging voor schrapers. Hoewel we niet langer kunnen vertrouwen op het parseren van de onbewerkte HTML-inhoud, staat er nog steeds een overvloed aan gegevens op de pagina – we moeten alleen weten waar we moeten kijken.

In deze uitgebreide gids verkennen we verschillende methoden, tools en technieken die kunnen worden gebruikt om verborgen webgegevens te extraheren.

Wat zijn verborgen webgegevens?

Verborgen webgegevens verwijzen naar alle gegevens die niet direct zichtbaar zijn in de onbewerkte HTML-bron van de pagina. Dit bevat:

  • Gegevens worden dynamisch geladen via JavaScript nadat de pagina is geladen. Als u bijvoorbeeld de inhoud van een <div> tag door dynamisch gemaakte HTML-elementen in te voegen.

  • Gegevens opgeslagen in JavaScript-variabelen en objecten die zijn ingebed in <script> labels. Vaak JSON-objecten die volledige datasets bevatten.

  • HTML-inhoud gegenereerd op basis van gebruikersactie via AJAX-verzoeken. Bijvoorbeeld het uitbreiden van commentaarthreads of oneindige scrollpaginering.

  • Interne API-verzoekgegevens en metagegevens die door de frontend worden gebruikt om te functioneren. Bijvoorbeeld CSRF-tokens, gebruikersinformatie, tijdelijke caches.

  • Verduisterde en gecodeerde gegevens met als doel te voorkomen dat scrapers er toegang toe krijgen.

Het gemeenschappelijke thema is dat deze gegevens niet beschikbaar zijn in de originele HTML die door de server wordt geretourneerd, maar later worden gegenereerd door het JavaScript dat op de pagina wordt uitgevoerd.

Moderne dynamische websites zijn sterk afhankelijk van deze techniek om snelle frontend-ervaringen op te bouwen. Alle gegevens kunnen worden verborgen en indien nodig op een elegante manier in kleine stukjes worden weergegeven.

Helaas betekent dit dat scrapers iets harder moeten werken om bij die gegevens te komen. Laten we eens kijken naar enkele manieren waarop we dat efficiënt kunnen doen.

Verborgen gegevens vinden in HTML

De eerste stap is bevestigen of de gewenste gegevens inderdaad ergens in de JavaScript-pagina verborgen zijn.

Hier is een eenvoudige methode om te controleren:

  • Laad de doelpagina in de browser en zoek een unieke gegevensidentificatie die we willen schrapen. Bijvoorbeeld een productnaam of ID.

  • Schakel JavaScript uit in de browser en laad de pagina opnieuw. Dit kan gedaan worden in de ontwikkelaarstools.

  • Controleer of de unieke identificatie nog steeds aanwezig is in de onbewerkte HTML-broncode.

Als de gegevens verdwenen zijn, worden deze hoogstwaarschijnlijk dynamisch weergegeven door JavaScript bij het laden van de pagina.

Nu moeten we door de HTML-bron graven om te ontdekken waar en hoe deze die inhoud genereert.

Gegevens uit tags extraheren

Een van de meest voorkomende plaatsen waar verborgen gegevens zich bevinden, is binnenin <script> labels.

Dit kunnen JSON-objecten, JavaScript-variabelen, volledige datasets of code zijn die de pagina manipuleert.

Bijvoorbeeld:

<html>
<body>

  <div id="product"></div>

  <script>
    // product data as javascript object 
    var data = {
      "product": {
        "name": "Super Product",
        "price": 99.99
      }
    }

    // data rendered on page load
    document.getElementById("product").innerHTML = data.product.name + ": £" + data.product.price;

  </script>

</body>  
</html>

Hier worden de daadwerkelijke productgegevens opgeslagen in een JavaScript-objectvariabele genaamd data.

Het product <div> is om te beginnen leeg en wordt dynamisch ingevuld bij het laden van de pagina.

Om deze gegevens te extraheren, moeten we dus eerst de relevante vinden <script> tag in de onbewerkte HTML. Dit kan gedaan worden met elke HTML-parseerbibliotheek zoals BeautifulSoup of Parsel:

# extract scripts from HTML with BeautifulSoup
from bs4 import BeautifulSoup

html = # page HTML 
soup = BeautifulSoup(html, ‘html.parser‘)

scripts = soup.find_all(‘script‘)

Vervolgens moeten we de gegevens specifiek uit de scriptinhoud extraheren.

Methode 1: Laden als JSON

Als de gegevens een geldig JSON-object zijn, kunnen we deze eenvoudigweg rechtstreeks met Python laden json module:

import json

# find script with data variable 
script = soup.find(‘script‘, text=lambda t: ‘data =‘ in t)

# load json directly
data = json.loads(script.string)

print(data[‘product‘])
# {‘name‘: ‘Super Product‘, ‘price‘: 99.99}

Dit werkt prima als de scripttag dit specificeert type="application/json".

Methode 2: Regex-matching

Voor complexere gegevens moeten we de onbewerkte JavaScript-code zelf parseren. Dit is waar reguliere expressies van pas komen.

We kunnen de code scannen en delen eruit halen die overeenkomen met een patroon, zoals ons data-object.

import re
import json

script = soup.find(‘script‘, text=lambda t: ‘data =‘ in t)

# match the data object by surrounding syntax 
match = re.search(r‘data = ({.+})‘, script.string)

# load matched json 
data = json.loads(match.group(1))

print(data[‘product‘])  
# {‘name‘: ‘Super Product‘, ‘price‘: 99.99}

De sleutel is het zorgvuldig vervaardigen van een regex-patroon dat op unieke wijze de dataset identificeert die we willen uit de rest van de code.

Methode 3: JavaScript-parsering

Voor geavanceerd schrapen willen we misschien de volledige JavaScript-code parseren, inclusief variabelen, functies en objecten.

Hierdoor kunt u alle gegevens extraheren met behoud van de oorspronkelijke structuur en context.

We kunnen bibliotheken gebruiken zoals PyJavascript en Js2Py JavaScript in Python interpreteren.

Bijvoorbeeld met PyJavascript:

import javascript

script = soup.find(‘script‘, text=lambda t: ‘data =‘ in t)

# init JavaScript interpreter 
js = javascript.Interpreter()

# run script to define data variable
js.execute(script.string)

# access parsed data object
print(js.context[‘data‘][‘product‘])
# {‘name‘: ‘Super Product‘, ‘price‘: 99.99} 

Hierdoor kunnen we gebruik maken van de volledige JavaScript-omgeving, naast alleen de datasets die we willen.

API-gegevens uit JavaScript schrapen

API's verzorgen het grootste deel van het dynamische gedrag op moderne websites. JavaScript doet verzoeken om gegevens te laden, formulieren in te dienen of interacties te activeren.

Door in de paginacode te graven, kunnen we deze API-eindpunten vinden en de verzoeken om gegevens te extraheren nabootsen.

Hier is bijvoorbeeld een eenvoudig script dat productgegevens laadt uit een /api/products/123 eindpunt:

async function loadProduct(){

  let response = await fetch(‘/api/products/123‘);

  let product = await response.json();

  // render product data to page
  document.getElementById("product").innerHTML = product.name;

}

loadProduct();

Zodra we dit script in de HTML hebben gevonden, kunnen we:

  • Pak de API-URL uit het fetch() Bellen

  • Analyseer de AJAX-aanvraag- en antwoordformaten

  • Repliceer het API-verzoek rechtstreeks in Python met bibliotheken zoals Requests

Hierdoor kunnen gegevens worden verzameld uit API's waarvan JavaScript afhankelijk is, zonder dat er browsercode wordt uitgevoerd.

Gegevens zoeken in JavaScript-variabelen

Paginagegevens worden ook vaak rechtstreeks in JavaScript-variabelen opgeslagen.

Bijvoorbeeld:

// javascript data
var products = [
  {name: "Product 1", price: 19.99}, 
  {name: "Product 2", price: 24.99}
];

function renderProducts(){
  // loop through products and render HTML
} 

Hier wordt de volledige productenlijst opgeslagen in een variabele genaamd products.

Om dit te extraheren, moeten we eerst de naam van de variabele vinden die overeenkomt met onze doelgegevensstructuur. We kunnen een vergelijkbare regex-aanpak gebruiken:

import re
import json

# find products variable
script = soup.find(‘script‘, text=lambda t: ‘var products =‘ in t)

# match products json
match = re.search(r‘var products = ({.+});‘, script.string)  
data = json.loads(match.group(1))

print(data)
# [{name: "Product 1", price: 19.99}, {name: "Product 2", price: 24.99}]

Als de gegevensstructuur complexer is, kunnen we de volledige JavaScript-omgeving parseren om toegang te krijgen tot alle variabelen die binnen het bereik vallen.

Inhoud schrapen die via AJAX is geladen

Websites laden inhoud vaak dynamisch via AJAX nadat de pagina is geladen.

Bijvoorbeeld het uitbreiden van commentaarthreads, oneindige scroll-paginering of tabbladen.

Deze inhoud is niet aanwezig in de initiële HTML, maar wordt indien nodig opgevraagd bij de server.

We kunnen deze AJAX-fragmenten schrapen door:

  • Netwerkverzoeken op de pagina monitoren om AJAX-URL's te identificeren.

  • AJAX-verzoeken reconstrueren en rechtstreeks vanuit Python-code verzenden.

  • Parseren van de AJAX-antwoorden die HTML/JSON-gegevens bevatten.

Beschouw bijvoorbeeld dit script dat gepagineerde gegevens laadt bij het scrollen:

// initially loaded page data
var results = [ /* initial page of data */]; 

// paginate on scroll
window.addEventListener(‘scroll‘, function() {

  var page = results.length / 20 + 1;

  // request next page
  fetch(‘/data?page=‘ + page)
    .then(res => res.json())
    .then(data => {
      results.push(...data);

      // render new data
    });

});

Hier kunnen we zien dat het pagina's opvraagt /data eindpunt en het toevoegen van inhoud aan results variabel.

We kunnen deze verzoeken repliceren en de gegevens rechtstreeks schrapen, zodat we niet de volledig weergegeven HTML hoeven te parseren.

JavaScript uitvoeren met Headless Browsers

Voor het ultieme op het gebied van dynamisch schrapen van inhoud kunnen we een volledige headless browser opzetten, de pagina laden en rechtstreeks toegang krijgen tot de JavaScript-omgeving.

Dit maakt het evalueren van code mogelijk, het laden van dynamische inhoud en toegang tot alle gegevens, functies of DOM-elementen die beschikbaar zijn op de livepagina.

Hier is een voorbeeld met Toneelschrijver in Python:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:

  browser = p.chromium.launch()
  page = browser.new_page()

  page.goto(‘https://targetpage.com‘)

  # evaluate browser context to get data
  data = page.evaluate(‘window.products‘) 

  browser.close()

print(data)

De sleutel gebruikt page.evaluate() om aangepaste JavaScript-code uit te voeren in de context van de geladen pagina.

Dit geeft ons volledige toegang om anderszins verborgen gegevens te schrappen.

Het nadeel is dat je een volledige browserinstantie moet starten, wat langzamer is dan directe HTTP-verzoeken. Deze methode moet dus spaarzaam worden gebruikt voor complexe pagina's.

Verduisterde en gecodeerde gegevens

Websites verdoezelen vaak opzettelijk hun JavaScript om scraping te voorkomen.

Enkele voorbeelden zijn:

  • Het verkleinen van namen van variabelen en functies tot betekenisloze tekens zoals a, b, fn1()

  • Datasets splitsen over meerdere variabelen en scripts

  • Gegevens versleutelen/coderen zodat deze niet voor mensen leesbaar zijn

  • Dynamisch samenstellen van gegevens tijdens runtime uit gefragmenteerde stukken

  • Technieken voor codebescherming, zoals inpakken, verduistering, anti-foutopsporing en VM-uitvoering

Dit kan het parseren van JavaScript erg lastig maken. Kleine codewijzigingen kunnen onze scrapers gemakkelijk kapot maken.

Er zijn een paar manieren om met sterk versluierde pagina's om te gaan:

  • Gebruik headless browsers zoals Playwright of Puppeteer om uitgevoerde code te laden in plaats van de versluierde bron rechtstreeks te analyseren.

  • Traceer de uitvoering van de code om te begrijpen hoe gegevens worden verzameld, bijvoorbeeld met behulp van browserontwikkelaarstools of proxying van browserverkeer.

  • Analyseer hoe echte gebruikers omgaan met de pagina om gegevensbronnen te identificeren.

  • Patronen komen overeen met bekende datastructuren – zoals productnamen, prijzen, ID’s – om relevante codedelen te lokaliseren, zelfs als variabelen onduidelijk zijn.

  • Voor versleuteling kunt u proberen versleutelingssleutels te vinden of decoderingsalgoritmen reverse-engineeren.

In de loop van de tijd kunnen we veerkracht opbouwen door schrapers te ontwikkelen die zich aanpassen aan verduisteringsveranderingen.

Verborgen API's schrapen met proxy's

Verborgen web-API's maken vaak gebruik van geavanceerde anti-scraping-technieken zoals IP-snelheidsbeperking, captcha en botdetectie om toegang te voorkomen.

Dit is waar proxy's erg handig zijn voor scrapen. Door verzoeken via residentiële IP's te routeren, kunnen we veel beveiligingen omzeilen en op grote schaal toegang krijgen tot API's.

Enkele tips voor het scrapen met proxy's:

  • Gebruik regelmatige proxyrotatie om te voorkomen dat u wordt geblokkeerd op specifieke IP's

  • Schakel proxyrotatie in op basis van regio's of ISP's voor grote diversiteit

  • Gebruik backconnect-proxy's die duizenden unieke IP's bieden waar u doorheen kunt bladeren

  • Beperk de aanvraagsnelheid per proxy om echt gebruikersgedrag na te bootsen

  • Gebruik proxy-autorisatie om echte apparaten na te bootsen, niet alleen anonieme IP-adressen

  • Controleer en behandel veelvoorkomende blokkades zoals captcha's, blokkerende pagina's en 429's

Met de juiste proxy-instellingen hebben we toegang tot vrijwel elke doelsite of verborgen API.

Schraapservices voor verborgen gegevens

Er zijn ook beheerde scraping-services die speciaal zijn gebouwd voor het extraheren van door JavaScript weergegeven gegevens.

Deze bieden mogelijkheden voor browserautomatisering, proxybeheer en JavaScript-uitvoering.

Enkele voorbeelden zijn:

SchrapenBee – Browser- en proxy-API die JS op pagina's kan evalueren.

SchraperAPI – Headless browser-API met automatische proxyrotatie.

Apify – Actor-runtime voor browserautomatisering op schaal.

ScrapeOps – Visuele browserautomatiseringsbouwer met JS-extractie.

ScrapFly – Niet-blokkeerbare scraping-API met miljoenen residentiële backconnect-proxy’s.

Deze services behandelen alle complexiteiten van dynamische paginaweergave en maken het schrapen van verborgen gegevens eenvoudig.

Key Takeaways

Hier zijn de belangrijkste punten voor het schrapen van verborgen websitegegevens:

  • Inspecteer pagina's zonder JavaScript om te bevestigen dat gegevens dynamisch worden geladen

  • Extraheer en parseer scripts, variabelen en JSON-objecten uit HTML

  • Analyseer en repliceer AJAX-verzoeken om toegang te krijgen tot verborgen API's

  • Gebruik proxy's en headless browsers wanneer dat nodig is voor zware JS-sites

  • Patroonmatch en reverse-engineering van versluierde code

  • Pas schrapers aan om anti-botbeschermingen aan te kunnen

Met de juiste technieken kunnen vrijwel alle gegevens van openbare websites worden geëxtraheerd. We moeten alleen weten waar we moeten kijken!

Tags:

Doe mee aan het gesprek

Uw e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd *