C # HTMLAgilityPack VS espressioni regolari per l'estrazione di link da HTML

c# html-agility-pack html-parsing regex

Domanda

Sto scrivendo un web crawler C # e quando HTMLAgilityPack's LoadHTML la profilazione posso vedere che HTMLAgilityPack's LoadHTML metodo HTMLAgilityPack's LoadHTML utilizza il 10% del totale dell'utilizzo della CPU. Mi piacerebbe provare ad abbassarlo.

Sono sicuro che un'espressione regolare sarebbe più veloce ma, mentre guardo gli esempi di estrazione di collegamenti su SO, vedo che tutti dicono che questo metodo dovrebbe essere evitato a favore di un parser html come HTMLAgilityPack .

Come tutto quello che devo fare è estrarre i link da HTML sta usando HTMLAgilityPack su kill?

I motivi per preferire un parser HTML sono applicabili al mio caso in quanto lo sto solo utilizzando per estrarre i link?


HTML scaricato con WebClient quindi confrontato.

Usando href\\s*=\\s*(?:[\"'](?<1>[^\"']*)[\"']|(?<1>\\S+)) (quindi ritagliare e aggiungere a un elenco) è molto più veloce di HTMLAgilityPack.

43 millisecondi rispetto a 3 in modo coerente.


Vedi il mio codice su pastebin

Risposta accettata

I motivi per preferire un parser HTML sono applicabili al mio caso in quanto lo sto solo utilizzando per estrarre i link?

Nel tuo caso il parser HTML è eccessivo come i tuoi test hanno mostrato.

Le persone che rispondono su SO la usano come risposta automatica a tutte le domande regex. Uno dovrebbe usare lo strumento se uno ha effettivamente bisogno di analizzare il dominio dell'HTML in modo più solido.


I pregiudizi nei confronti delle espressioni regolari vengono riscontrati da persone che si sentono troppo lente o ingombranti [da apprendere]. C'è un merito in merito a ciò che viene proposto da loro per determinate operazioni, in quanto il testo ottimizzato specifico per la ricerca di utilità ha prestazioni migliori. Certo, sono d'accordo, ma per respingere regex di mano, beh, questo è il par per il corso su StackOverflow.

Perché è così? A volte l'analisi è semplicemente errata perché il pattern fornito introduce un sacco di backtracking non necessario e non è ottimizzato. Quegli handicap regex fuori dal cancello. Uno deve imparare il linguaggio regex e capire cosa sta facendo per mettere a punto il motore di regex per non inquinare.

Ad esempio, ho eseguito il tuo stesso test del codice C #, ma ho utilizzato un modello ottimizzato del tuo e del mio ed è stato in grado di ridurlo a 1 millisecondo in modo coerente!

La maggior parte delle persone apprende la corrispondenza di modelli di base eseguendo ricerche con un * . Quando imparano per la prima volta regex usano * con il . come .* . Questo passo con l'uso indiscriminato del simbolo * condurrà molto probabilmente a un modello non iniziale all'inferno di backtracking e risposte lente.

A meno che tu non sappia empiricamente che non ci sono oggetti, usa il + invece.


Nel 2009 ho scritto di questo argomento sul mio blog Are C # .Net Regular Expressions Fast Enough for You?



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché