Gestructureerde gegevens schrapen met PowerShell en HTML Agility Pack

Laatste update: 10/10/2025
Auteur: Isaac
  • Html Agility Pack maakt robuust parsen en bevragen van HTML met XPath/LINQ mogelijk.
  • PowerShell en C# dekt statisch scrapen; Selenium lost pagina's op met JavaScript.
  • Met CsvHelper en IronPDF kunt u eenvoudig gegevens exporteren naar CSV of rapporten genereren in PDF.
  • Door gebruik te maken van proxies worden blokkades verminderd en is regionaal gericht scrapen mogelijk.

Schrapen met PowerShell en HTML Agility Pack

Als u op zoek bent naar een praktische manier om gestructureerde gegevens Zonder dat je met reguliere expressies hoeft te rommelen, is de combinatie van PowerShell met het HTML Agility Pack een van die oplossingen die je tijd en moeite bespaart. Met deze stack kun je door de DOM navigeren, knooppunten vinden met XPath of LINQ en tekst, attributen of HTML betrouwbaar lezen, zelfs als de opmaak niet perfect is.

In de volgende regels combineren we het beste van verschillende benaderingen: PowerShell, C# en Selenium om zowel statische als dynamische content te dekken, praktijkvoorbeelden (zoals het extraheren van de inhoud van Craigslist-advertenties), CSV-export en zelfs de mogelijkheid om resultaten naar PDF te converteren met IronPDF. Alles met Tricks nuttig als het gebruik van proxies om crashes te voorkomen en aanbevelingen om uw selectoren in de loop van de tijd robuust te houden.

Wat is HTML Agility Pack en waarom is het zo nuttig?

HTML Agility Pack (HAP) is een .NET-bibliotheek die HTML parseert in een knooppuntboom die je kunt navigeren, raadplegen en bewerken. In tegenstelling tot andere, meer kwetsbare benaderingen, tolereert HAP slecht geformatteerde HTML en kun je met een eenvoudige API door de DOM navigeren met XPath of LINQ.

De sterke punten zijn: milde analyse (verslindt imperfecte HTML), DOM-manipulatie (toevoegen, verwijderen of wijzigen van knooppunten/attributen), ondersteuning voor XPath en LINQen goede prestaties, zelfs bij grote documenten. Bovendien is het ontwerp uitbreidbaar, zodat u indien nodig aangepaste filters of handlers kunt implementeren.

HTML laden en parseren met HAP: bestand, string of web

Om te beginnen kunt u HTML-inhoud laden vanuit een lokaal bestand, vanuit een tekenreeks in het geheugen of rechtstreeks vanuit een URL. De sleutelklasse is HtmlDocument, en voor het web is het zeer comfortabel in gebruik HTMLWeb en de Load()-methode.

// Desde archivo
var doc = new HtmlDocument();
doc.Load(filePath);

// Desde cadena
var doc2 = new HtmlDocument();
doc2.LoadHtml(htmlString);

// Desde la web
var web = new HtmlWeb();
var doc3 = web.Load("http://example.com/");

Zodra het document is geladen, krijgt u toegang tot het hoofdknooppunt met DocumentNodeVanaf daar kun je selecteer knooppunten via XPath of met LINQ en lees eigenschappen zoals OuterHtml, InnerText, Name of de attributenverzameling met totaal gemak.

Knooppunten selecteren en lezen: XPath, kenmerken en tekstopschoning

Met XPath kunt u specifieke elementen lokaliseren zonder dat u moeite hoeft te doen met HTML. De bibliotheek biedt SelectSingleNode() voor één resultaat en SelecteerNodes() als je er meerdere verwacht.

// Un solo nodo (por ejemplo, el <title> de la página)
var titleNode = doc.DocumentNode.SelectSingleNode("//head/title");

// Varios nodos (por ejemplo, todos los <article>)
var articles = doc.DocumentNode.SelectNodes("//article");

// Lectura de información útil
var name = titleNode.Name;            // etiqueta del nodo
var html = titleNode.OuterHtml;       // HTML completo del nodo
var text = titleNode.InnerText;       // texto plano del nodo

Als uw tekst HTML-entiteiten bevat, kunt u de inhoud 'opschonen' met behulp van hulpprogramma's zoals HtmlEntity.DeEntitize() of, als u de voorkeur geeft aan BCL, Systeem.Net.WebUtility.HtmlDecode()Hierdoor krijgt u een natuurlijkere tekst die direct als data verwerkt kan worden.

// Limpieza de entidades HTML en texto extraído
var limpio = HtmlEntity.DeEntitize(titleNode.InnerText);
// o
var limpio2 = System.Net.WebUtility.HtmlDecode(titleNode.InnerText);

PowerShell + HTML Agility Pack: inspectie, methoden en extractie in de praktijk

Veel teams geven de voorkeur aan PowerShell omdat het zeer snelle scraping-prototyping mogelijk maakt. Je kunt de HAP-DLL laden (bijv. versie 1.11.59) en gebruik de klassen ervan vanuit scripts. Als je met modules zoals PSParseHTML hebt gewerkt, heb je eigenlijk HAP gebruikt.

# Cargar la DLL (ajusta la ruta a tu entorno)
$hapPath = 'C:\ruta\a\HtmlAgilityPack.dll'
[Reflection.Assembly]::LoadFile($hapPath) | Out-Null

# Descargar una página y cargarla en HtmlDocument
$dest = '$env:TEMP\page.htm'
$wc = New-Object System.Net.WebClient
$wc.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$wc.DownloadFile('http://localhost/mihtml.html', $dest)

$doc = New-Object HtmlAgilityPack.HtmlDocument
$doc.Load($dest)
$root = $doc.DocumentNode

# Por ejemplo, recorrer filas de una tabla
$rows = $root.Descendants('tr')
foreach ($row in $rows) {
    $cells = $row.Descendants('td')
    if ($cells.Count -ge 2) {
        Write-Host ($cells[0].InnerText + ' - ' + $cells[1].InnerText)
    }
}

Een veelvoorkomende vraag bij het verkennen van objecten in PowerShell is waar het vandaan komt Attribuutwaarde ophalen() en waarom er meerdere handtekeningen verschijnen. In HtmlAgilityPack stellen knooppunten die methode bloot met overloads die de attribuutnaam en een standaardwaarde accepteren om te converteren naar tekenreeks, int, bool, enz. PowerShell kan het weergeven als een generieke methode (T) of verschillende overloads, afhankelijk van de type-engine, maar in de praktijk zult u het als volgt gebruiken:

# Obtener un atributo (con valor por defecto si no existe)
$href = $node.GetAttributeValue('href', $null)
$tabIndex = $node.GetAttributeValue('tabindex', -1)
$esActivo = $node.GetAttributeValue('data-active', $false)

Regex voor HTML? Beter niet. Als je de body van een advertentie wilt extraheren die is ingepakt in een met een specifieke id is het stabieler in gebruik xpad dan te vechten met fragiele patronen. Bijvoorbeeld, voor een geval als … :

# Seleccionar el <section> por id (incluso si hay espacios en el id)
$section = $root.SelectSingleNode("//section[@id='posting body']")
if ($section) {
    $texto = $section.InnerText
}

Deze aanpak is schoon en onderhoudbaar: als de structuur verandert, past u de xpad En dat is alles. Je vermijdt typische HTML-regexfouten (nesting, spaties, attributen in verschillende volgordes, enz.).

  SEO-tips en -strategieën voor Baidu

Een snelle blik met VB.NET en nog een voorbeeld in PowerShell

Hetzelfde idee geldt voor VB.NET of C#: we downloaden de HTML, laden deze in HtmlDocument, we lokaliseren rijen en cellen en halen hun tekst eruit met heel weinig code.

' VB.NET: recorrer una tabla simple
Using client As New Net.WebClient()
    Dim tmp = IO.Path.GetTempFileName()
    client.Credentials = CredentialCache.DefaultNetworkCredentials
    client.DownloadFile(_URL, tmp)

    Dim doc = New HtmlAgilityPack.HtmlDocument()
    doc.Load(tmp)

    Dim root = doc.DocumentNode
    Dim filas = root.Descendants("tr").ToList()

    For Each fila In filas
        Dim tds = fila.Descendants("td").ToList()
        If tds.Count >= 2 Then
            Console.WriteLine(tds(0).InnerText & ": " & tds(1).InnerText)
        End If
    Next
End Using

Zoals u kunt zien, biedt HAP een solide parsing-engine en veelzijdig. Het verschil tussen de talen zit in de syntaxis; de workflow is identiek: laden, knooppunten selecteren en inhoud lezen.

Statisch scrapen in C# stap voor stap: van XPath naar CSV

Voor sites met statische content (de HTML bevat de data al), downloadt u eenvoudig de pagina en parseert u de knooppunten. Laten we de volledige flow bekijken: installeer HAP, laad een pagina, selecteer rijen op XPath, wijs toe aan objecten en exporteer naar CSV met CsvHelper.

1) Installeer HtmlAgilityPack van NuGet. 2) Laad de URL met HtmlWeb.Load(). 3) Haal de knooppunten op met XPath. 4) Haal tekst uit elke cel. 5) Exporteer de objecten naar CSV met CsvHelper.

using HtmlAgilityPack;
using System.Collections.Generic;

// URL de ejemplo (Wikipedia)
var url = "https://en.wikipedia.org/wiki/List_of_SpongeBob_SquarePants_episodes";
var web = new HtmlWeb();
var document = web.Load(url);

// XPath que selecciona filas de las tablas de episodios
var nodes = document.DocumentNode.SelectNodes(
    "//*[@id='mw-content-text']/div[1]/table[position()>1 and position()<15]/tbody/tr[position()>1]");

// Clase para mapear resultados
public class Episode {
    public string OverallNumber { get; set; }
    public string Title { get; set; }
    public string Directors { get; set; }
    public string WrittenBy { get; set; }
    public string Released { get; set; }
}

var episodes = new List<Episode>();
foreach (var node in nodes) {
    episodes.Add(new Episode {
        OverallNumber = HtmlEntity.DeEntitize(node.SelectSingleNode("th[1]").InnerText),
        Title        = HtmlEntity.DeEntitize(node.SelectSingleNode("td[2]").InnerText),
        Directors    = HtmlEntity.DeEntitize(node.SelectSingleNode("td[3]").InnerText),
        WrittenBy    = HtmlEntity.DeEntitize(node.SelectSingleNode("td[4]").InnerText),
        Released     = HtmlEntity.DeEntitize(node.SelectSingleNode("td[5]").InnerText)
    });
}

Om de CSV te schrijven, maakt CsvHelper de uitvoer veel eenvoudiger. Je maakt gewoon een StreamWriter aan en roept deze aan. SchrijfRecords() met uw sterk getypte lijst.

using CsvHelper;
using System.Globalization;
using System.IO;

using (var writer = new StreamWriter("output.csv"))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) {
    csv.WriteRecords(episodes);
}

Op deze manier kan iedereen het CSV-bestand in Excel openen en ermee werken. gestructureerde gegevens Zonder de code aan te raken. Het is een eenvoudige, betrouwbare en makkelijk te onderhouden flow als de paginastructuur verandert: gewoon je XPath bijwerken en klaar.

  Eenvoudige manieren om een ​​iPhone te repareren die vastzit in de zoommodus

Wanneer HTML de data niet levert: dynamisch, AJAX en Selenium

Op dynamische sites kan de initiële HTML leeg zijn en geeft JavaScript de gegevens weer na XHR-verzoeken. Omdat HAP niet wordt uitgevoerd JavaScriptheb je een headless browser zoals Selenium nodig om eerst te renderen en later te extraheren.

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

var url = "https://en.wikipedia.org/wiki/List_of_SpongeBob_SquarePants_episodes";
var chromeOptions = new ChromeOptions();
chromeOptions.AddArguments("headless");
var driver = new ChromeDriver(chromeOptions);

driver.Navigate().GoToUrl(url);

var rows = driver.FindElements(By.XPath(
    "//*[@id='mw-content-text']/div[1]/table[position()>1 and position()<15]/tbody/tr[position()>1]"));

foreach (var row in rows) {
    var title = row.FindElement(By.XPath("td[2]")).Text;
    // ...
}

Voeg in scenario's met lui laden of langzame verzoeken een WebDriverWacht wachten tot er knooppunten verschijnen of tot Ajax voltooid is. Het is zwaarder dan HAP, maar voor dynamische pagina's is het de juiste aanpak.

Belangrijkste HAP-beperking en WebView-alternatief

HAP parseert de DOM zoals deze van de server arriveert, d.w.z. voert JS niet uitAls uw doelsite scripts nodig heeft om de inhoud weer te geven, kunt u naast Selenium de pagina ook in een besturingselement laden WebView/WebBrowser die JavaScript uitvoert en, zodra deze klaar is, de resulterende HTML doorstuurt naar HtmlAgilityPack. Zo combineer je echte rendering met robuuste parsing.

Gebruiksscenario's: wat te doen met de gegevens

Zodra je je objecten in het geheugen hebt, is de grens je verbeelding: ze opslaan in een database, ze transformeren in JSON om API's aan te roepen, CSV's voor het businessteam te genereren of ze te uploaden naar periodieke rapporten. De sleutel is om de resultaten te vertalen naar formaten die uw organisatie al gebruikt.

Privacy, blokkering en regionaal scrapen met behulp van proxy's

Door op grote schaal te scrapen, kunnen sites patronen detecteren en uw website blokkeren. IPHet gebruik van proxyservers (bij voorkeur met een roterend adres) helpt blokkades te voorkomen, de belasting te verdelen en toegang te krijgen tot regionale versies van dezelfde website. Een goede provider laat u de exitlocatie kiezen, ideaal voor marktonderzoek of internationale prijsbepaling.

De proxy's roterend Ze wijzen aan elk verzoek een ander IP-adres toe, waardoor het voor antibotsystemen moeilijk is om ze te volgen. Als u bovendien catalogi of prijzen wilt bekijken die per land verschillen, kiest u de proxylocatie om exact hetzelfde beeld te krijgen als een echte gebruiker in die regio.

Integreer HtmlAgilityPack met IronPDF: van HTML naar PDF

Er zijn scenario's waarin u resultaten in een document moet verpakken. Daar komt IronPDF om de hoek kijken: met HAP extraheert en stelt u de gewenste HTML samen en met IronPDF Je converteert het naar PDF met behoud van stijl en lay-out. Perfect voor rapporten of deliverables die buiten het technische team worden gedeeld.

  Hoe MSVCP140.dll te repareren: oorzaken, oplossingen en aanbevolen procedures

Het installeren van IronPDF is net zo eenvoudig als het toevoegen van het NuGet-pakket. Indien gewenst, is er ook de mogelijkheid om de DLL Handmatig. Zodra je een referentie hebt gemaakt, maak je een HtmlToPdf en render je een HTML-string die je zelf genereert op basis van de gescrapete content.

using HtmlAgilityPack;
using System.Text;
// using IronPdf;  // Asegúrate de referenciar IronPDF

var web = new HtmlWeb();
var doc = web.Load("https://ironpdf.com/");

var nodes = doc.DocumentNode.SelectNodes(
    "//h1[@class='product-homepage-header product-homepage-header--ironpdf']");

var htmlContent = new StringBuilder();
foreach (var n in nodes) {
    htmlContent.Append(n.OuterHtml);
}

var renderer = new IronPdf.HtmlToPdf();
var pdf = renderer.RenderHtmlAsPdf(htmlContent.ToString());
pdf.SaveAs("output.pdf");

Als u kopteksten, voetteksten of nummering wilt toevoegen of pagina's wilt samenstellen met secties die uit verschillende URL's zijn gehaald, kunt u de uitvoer aanpassen voordat u deze naar de engine stuurt. PDF voor een gepolijster resultaat.

Goede praktijken voor selectoren en onderhoud

  • Geef de voorkeur aan stabiele kenmerken (betekenisvolle id's of klassen) boven kwetsbare indexen zoals div[3]/span[2].
  • Vermijd regex in HTML als er een DOM/XPath-alternatief is.
  • Gebruik HtmlEntity.DeEntitize/HtmlDecode om entiteiten op te schonen.
  • Centraliseer XPaths in constanten en documenteer hun bedoeling.
  •  Implementeert foutcontroles: nulknooppunten, time-outs, structurele veranderingen.
  • Voeg voor dynamiek expliciete wacht- en elementaanwezigheidsvoorwaarden toe.

Het is ook een goed idee om echte HTML-voorbeelden op te nemen in tests om fouten op te sporen wanneer de website verandert. Het onderhouden van een kleine testsuite voor je XPaths en mappings is goedkoop en voorkomt productieproblemen, vooral wanneer er meerdere zijn. bronnen van gegevens.

Tips voor prestaties en uitbreidbaarheid

HAP is geoptimaliseerd voor het verwerken van grote documenten met een redelijk geheugengebruik. Als u echter veel pagina's verwerkt, kunt u parallelisatie overwegen. downloads met limieten (bijv. SemaphoreSlim) en normaliseert de HTML vlak voor het extraheren. Als u speciale regels nodig hebt, kunt u de pijplijn uitbreiden met uw eigen filters voordat u uw objecten construeert.

In gemengde omgevingen is PowerShell ideaal voor het orkestreren van taken (downloads, proxyrotatie, uitvoering van parser C# gecompileerde scripts) en consolideer de resultaten. Door scripts te combineren met .NET-hulpprogramma's krijgt u flexibiliteit zonder dat dit ten koste gaat van de prestaties.

Als je met reguliere expressies werkt, zul je merken dat DOM/XPath minder onderhoud vereist en veel leesbaarder is. Het is gebruikelijk dat een goed doordachte selector maandenlang meegaat, zelfs met kleine aanpassingen. markup van de doelwebsite.

Dit hele ecosysteem (HtmlAgilityPack voor parsing, Selenium voor rendering indien nodig, CsvHelper voor export en IronPDF voor presentatie) sluit perfect aan bij praktische extractie- en rapportageworkflows. Met PowerShell, C# of VB.NET kunt u schaalbare oplossingen bouwen, en met de ondersteuning van proxies, veerkrachtiger te opereren in het geval van lockdowns, regionale verschuivingen of piekbelastingen.