Puoi fornire esempi di analisi HTML?

Come si analizza l’HTML con una varietà di lingue e librerie di analisi?


Quando rispondi:

I commenti individuali saranno collegati a risposte a domande su come analizzare HTML con espressioni regolari come modo per mostrare il modo giusto di fare le cose.

Per motivi di coerenza, chiedo che l’esempio analizzi un file HTML per l’ href nei tag di ancoraggio. Per semplificare la ricerca di questa domanda, ti chiedo di seguire questo formato

Lingua: [nome della lingua]

Libreria: [nome della libreria]

 [example code] 

Si prega di rendere la biblioteca un link alla documentazione per la biblioteca. Se si desidera fornire un esempio diverso dall’estrazione di collegamenti, includere anche:

Scopo: [cosa fa l’analisi]

Lingua: JavaScript
Libreria: jQuery

 $.each($('a[href]'), function(){ console.debug(this.href); }); 

(usando firebug console.debug per l’output …)

E caricando qualsiasi pagina html:

 $.get('http://stackoverflow.com/', function(page){ $(page).find('a[href]').each(function(){ console.debug(this.href); }); }); 

Usato un’altra funzione per questo, penso che sia più pulito quando si concatenano i metodi.

Lingua: C #
Libreria: HtmlAgilityPack

 class Program { static void Main(string[] args) { var web = new HtmlWeb(); var doc = web.Load("http://www.stackoverflow.com"); var nodes = doc.DocumentNode.SelectNodes("//a[@href]"); foreach (var node in nodes) { Console.WriteLine(node.InnerHtml); } } } 

lingua: Python
biblioteca: BeautifulSoup

 from BeautifulSoup import BeautifulSoup html = "" for link in ("foo", "bar", "baz"): html += '%s' % (link, link) html += "" soup = BeautifulSoup(html) links = soup.findAll('a', href=True) # find  with a defined href attribute print links 

produzione:

 [foo, bar, baz] 

anche ansible:

 for link in links: print link['href'] 

produzione:

 http://foo.com http://bar.com http://baz.com 

Lingua: Perl
Libreria: pQuery

 use strict; use warnings; use pQuery; my $html = join '', "", (map { qq($_) } qw/foo bar baz/), ""; pQuery( $html )->find( 'a' )->each( sub { my $at = $_->getAttribute( 'href' ); print "$at\n" if defined $at; } ); 

lingua: shell
libreria: lynx (beh, non è una libreria, ma nella shell, ogni programma è di tipo libreria)

 lynx -dump -listonly http://news.google.com/ 

lingua: Ruby
biblioteca: Hpricot

 #!/usr/bin/ruby require 'hpricot' html = '' ['foo', 'bar', 'baz'].each {|link| html += "#{link}" } html += '' doc = Hpricot(html) doc.search('//a').each {|elm| puts elm.attributes['href'] } 

lingua: Python
libreria: HTMLParser

 #!/usr/bin/python from HTMLParser import HTMLParser class FindLinks(HTMLParser): def __init__(self): HTMLParser.__init__(self) def handle_starttag(self, tag, attrs): at = dict(attrs) if tag == 'a' and 'href' in at: print at['href'] find = FindLinks() html = "" for link in ("foo", "bar", "baz"): html += '%s' % (link, link) html += "" find.feed(html) 

lingua: Perl
libreria: HTML :: Parser

 #!/usr/bin/perl use strict; use warnings; use HTML::Parser; my $find_links = HTML::Parser->new( start_h => [ sub { my ($tag, $attr) = @_; if ($tag eq 'a' and exists $attr->{href}) { print "$attr->{href}\n"; } }, "tag, attr" ] ); my $html = join '', "", (map { qq($_) } qw/foo bar baz/), ""; $find_links->parse($html); 

Lingua Perl
Libreria: HTML :: LinkExtor

La bellezza di Perl è che hai moduli per compiti molto specifici. Come l’estrazione di link.

Programma completo:

 #!/usr/bin/perl -w use strict; use HTML::LinkExtor; use LWP::Simple; my $url = 'http://www.google.com/'; my $content = get( $url ); my $p = HTML::LinkExtor->new( \&process_link, $url, ); $p->parse( $content ); exit; sub process_link { my ( $tag, %attr ) = @_; return unless $tag eq 'a'; return unless defined $attr{ 'href' }; print "- $attr{'href'}\n"; return; } 

Spiegazione:

  • usa strict – triggers la modalità “strict” – facilita il potenziale debugging, non completamente rilevante per l’esempio
  • usa HTML :: LinkExtor – carica di modulo interessante
  • usa LWP :: Simple – solo un modo semplice per ottenere un html per i test
  • my $ url = ‘ http://www.google.com/ ‘ – da quale pagina estrarremo gli URL
  • my $ content = get ($ url) – recupera la pagina html
  • my $ p = HTML :: LinkExtor-> new (\ & process_link, $ url) – crea l’object LinkExtor, assegnandogli un riferimento alla funzione che verrà utilizzata come callback su ogni url e $ url da utilizzare come BASEURL per gli url relativi
  • $ p-> parse ($ content) – abbastanza ovvio, credo
  • uscita – fine del programma
  • sub process_link – inizio della funzione process_link
  • my ($ tag,% attr) – ottieni argomenti, che sono il nome del tag, e i suoi attributi
  • ritorna a meno che $ tag eq ‘a’ – salta l’elaborazione se il tag non è
  • ritorna a meno che non sia defeined $ attr {‘href’} – salta l’elaborazione se il tag non ha attributo href
  • print “- $ attr {‘href’} \ n”; – abbastanza ovvio immagino 🙂
  • ritorno; – completa la funzione

È tutto.

Lingua: Ruby
Biblioteca: Nokogiri

 #!/usr/bin/env ruby require 'nokogiri' require 'open-uri' document = Nokogiri::HTML(open("http://google.com")) document.css("html head title").first.content => "Google" document.xpath("//title").first.content => "Google" 

Lingua: Common Lisp
Libreria: chiusura Html , chiusura Xml , CL-WHO

(mostrato usando l’API DOM, senza usare l’API XPATH o STP)

 (defvar *html* (who:with-html-output-to-string (stream) (:html (:body (loop for site in (list "foo" "bar" "baz") do (who:htm (:a :href (format nil "http://~A.com/" site)))))))) (defvar *dom* (chtml:parse *html* (cxml-dom:make-dom-builder))) (loop for tag across (dom:get-elements-by-tag-name *dom* "a") collect (dom:get-attribute tag "href")) => ("http://foo.com/" "http://bar.com/" "http://baz.com/") 

Lingua: Clojure
Libreria: Enlive (un sistema di template e di trasformazione basato su selettori (à la CSS) per Clojure)


Espressione selettore:

 (def test-select (html/select (html/html-resource (java.io.StringReader. test-html)) [:a])) 

Ora possiamo fare quanto segue al REPL (ho aggiunto interruzioni di riga in test-select ):

 user> test-select ({:tag :a, :attrs {:href "http://foo.com/"}, :content ["foo"]} {:tag :a, :attrs {:href "http://bar.com/"}, :content ["bar"]} {:tag :a, :attrs {:href "http://baz.com/"}, :content ["baz"]}) user> (map #(get-in % [:attrs :href]) test-select) ("http://foo.com/" "http://bar.com/" "http://baz.com/") 

Avrai bisogno di quanto segue per provarlo:

Preambolo:

 (require '[net.cgrand.enlive-html :as html]) 

Test HTML:

 (def test-html (apply str (concat [""] (for [link ["foo" "bar" "baz"]] (str "" link "")) [""]))) 

lingua: Perl
libreria: XML :: Twig

 #!/usr/bin/perl use strict; use warnings; use Encode ':all'; use LWP::Simple; use XML::Twig; #my $url = 'http://stackoverflow.com/questions/773340/can-you-provide-an-example-of-parsing-html-with-your-favorite-parser'; my $url = 'http://www.google.com'; my $content = get($url); die "Couldn't fetch!" unless defined $content; my $twig = XML::Twig->new(); $twig->parse_html($content); my @hrefs = map { $_->att('href'); } $twig->get_xpath('//*[@href]'); print "$_\n" for @hrefs; 

avvertenza: è ansible ottenere errori di carattere ampio con pagine come questa (cambiando l’url con quello commentato si otterrà questo errore), ma la soluzione HTML :: Parser sopra non condivide questo problema.

Lingua: Perl
Libreria: HTML :: Parser
Scopo: come posso rimuovere i tag di estensione HTML nidificati e non utilizzati con un’espressione regolare Perl?

Lingua: Java
Librerie: XOM , TagSoup

Ho incluso XML intenzionalmente malformato e inconsistente in questo esempio.

 import java.io.IOException; import nu.xom.Builder; import nu.xom.Document; import nu.xom.Element; import nu.xom.Node; import nu.xom.Nodes; import nu.xom.ParsingException; import nu.xom.ValidityException; import org.ccil.cowan.tagsoup.Parser; import org.xml.sax.SAXException; public class HtmlTest { public static void main(final String[] args) throws SAXException, ValidityException, ParsingException, IOException { final Parser parser = new Parser(); parser.setFeature(Parser.namespacesFeature, false); final Builder builder = new Builder(parser); final Document document = builder.build("", null); final Element root = document.getRootElement(); final Nodes links = root.query("//a[@href]"); for (int linkNumber = 0; linkNumber < links.size(); ++linkNumber) { final Node node = links.get(linkNumber); System.out.println(((Element) node).getAttributeValue("href")); } } } 

TagSoup aggiunge uno spazio dei nomi XML che fa riferimento a XHTML nel documento per impostazione predefinita. Ho scelto di sopprimerlo in questo esempio. L'utilizzo del comportamento predefinito richiederebbe la chiamata a root.query per includere uno spazio dei nomi in questo modo:

 root.query("//xhtml:a[@href]", new nu.xom.XPathContext("xhtml", root.getNamespaceURI()) 

Lingua: C #
Libreria: System.XML (standard .NET)

 using System.Collections.Generic; using System.Xml; public static void Main(string[] args) { List matches = new List(); XmlDocument xd = new XmlDocument(); xd.LoadXml("..."); FindHrefs(xd.FirstChild, matches); } static void FindHrefs(XmlNode xn, List matches) { if (xn.Attributes != null && xn.Attributes["href"] != null) matches.Add(xn.Attributes["href"].InnerXml); foreach (XmlNode child in xn.ChildNodes) FindHrefs(child, matches); } 

Lingua: JavaScript
Biblioteca: DOM

 var links = document.links; for(var i in links){ var href = links[i].href; if(href != null) console.debug(href); } 

(usando firebug console.debug per l’output …)

Lingua: Racket

Libreria: (pianeta ashinn / html-parser: 1) e (planet clements / sxml2: 1)

 (require net/url (planet ashinn/html-parser:1) (planet clements/sxml2:1)) (define the-url (string->url "http://stackoverflow.com/")) (define doc (call/input-url the-url get-pure-port html->sxml)) (define links ((sxpath "//a/@href/text()") doc)) 

Sopra l’esempio usando i pacchetti dal nuovo sistema di pacchetti: html-parsing e sxml

 (require net/url html-parsing sxml) (define the-url (string->url "http://stackoverflow.com/")) (define doc (call/input-url the-url get-pure-port html->xexp)) (define links ((sxpath "//a/@href/text()") doc)) 

Nota: installa i pacchetti richiesti con ‘raco’ da una riga di comando, con:

 raco pkg install html-parsing 

e:

 raco pkg install sxml 

lingua: Python
libreria: lxml.html

 import lxml.html html = "" for link in ("foo", "bar", "baz"): html += '%s' % (link, link) html += "" tree = lxml.html.document_fromstring(html) for element, attribute, link, pos in tree.iterlinks(): if attribute == "href": print link 

lxml ha anche una class di selettori CSS per attraversare il DOM, che può rendere l’utilizzo molto simile all’utilizzo di JQuery:

 for a in tree.cssselect('a[href]'): print a.get('href') 

Lingua: PHP
Libreria: SimpleXML (e DOM)

 < ?php $page = new DOMDocument(); $page->strictErrorChecking = false; $page->loadHTMLFile('http://stackoverflow.com/questions/773340'); $xml = simplexml_import_dom($page); $links = $xml->xpath('//a[@href]'); foreach($links as $link) echo $link['href']."\n"; 

Lingua: Objective-C
Libreria: libxml2 + wrapper libxml2 di Matt Gallagher + ASIHTTPRequest di Ben Copsey

 ASIHTTPRequest *request = [ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://stackoverflow.com/questions/773340"]; [request start]; NSError *error = [request error]; if (!error) { NSData *response = [request responseData]; NSLog(@"Data: %@", [[self query:@"//a[@href]" withResponse:response] description]); [request release]; } else @throw [NSException exceptionWithName:@"kMyHTTPRequestFailed" reason:@"Request failed!" userInfo:nil]; ... - (id) query:(NSString *)xpathQuery WithResponse:(NSData *)resp { NSArray *nodes = PerformHTMLXPathQuery(resp, xpathQuery); if (nodes != nil) return nodes; return nil; } 

Lingua: Perl
Libreria: HTML :: TreeBuilder

 use strict; use HTML::TreeBuilder; use LWP::Simple; my $content = get 'http://www.stackoverflow.com'; my $document = HTML::TreeBuilder->new->parse($content)->eof; for my $a ($document->find('a')) { print $a->attr('href'), "\n" if $a->attr('href'); } 

Lingua: Python
Libreria: HTQL

 import htql; page="123"; query=":href,tx"; for url, text in htql.HTQL(page, query): print url, text; 

Semplice e intuitivo.

lingua: Ruby
biblioteca: Nokogiri

 #!/usr/bin/env ruby require "nokogiri" require "open-uri" doc = Nokogiri::HTML(open('http://www.example.com')) hrefs = doc.search('a').map{ |n| n['href'] } puts hrefs 

Quali uscite:

 / /domains/ /numbers/ /protocols/ /about/ /go/rfc2606 /about/ /about/presentations/ /about/performance/ /reports/ /domains/ /domains/root/ /domains/int/ /domains/arpa/ /domains/idn-tables/ /protocols/ /numbers/ /abuse/ http://www.icann.org/ mailto:iana@iana.org?subject=General%20website%20feedback 

Questo è uno spin minore di quello sopra, risultante in un output utilizzabile per un report. Ritorna solo il primo e l’ultimo elemento nella lista di hrefs:

 #!/usr/bin/env ruby require "nokogiri" require "open-uri" doc = Nokogiri::HTML(open('http://nokogiri.org')) hrefs = doc.search('a[href]').map{ |n| n['href'] } puts hrefs .each_with_index # add an array index .minmax{ |a,b| a.last < => b.last } # find the first and last element .map{ |h,i| '%3d %s' % [1 + i, h ] } # format the output 1 http://github.com/tenderlove/nokogiri 100 http://yokolet.blogspot.com 

Lingua: Java
Libreria: jsoup

 import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.xml.sax.SAXException; public class HtmlTest { public static void main(final String[] args) throws SAXException, ValidityException, ParsingException, IOException { final Document document = Jsoup.parse(""); final Elements links = document.select("a[href]"); for (final Element element : links) { System.out.println(element.attr("href")); } } } 

Lingua: Libreria PHP: DOM

 < ?php $doc = new DOMDocument(); $doc->strictErrorChecking = false; $doc->loadHTMLFile('http://stackoverflow.com/questions/773340'); $xpath = new DOMXpath($doc); $links = $xpath->query('//a[@href]'); for ($i = 0; $i < $links->length; $i++) echo $links->item($i)->getAttribute('href'), "\n"; 

A volte è utile mettere @ symbol prima di $doc->loadHTMLFile per sopprimere gli avvertimenti parsing html non validi

Usando phantomjs, salva questo file come extract-links.js:

 var page = new WebPage(), url = 'http://www.udacity.com'; page.open(url, function (status) { if (status !== 'success') { console.log('Unable to access network'); } else { var results = page.evaluate(function() { var list = document.querySelectorAll('a'), links = [], i; for (i = 0; i < list.length; i++) { links.push(list[i].href); } return links; }); console.log(results.join('\n')); } phantom.exit(); }); 

correre:

 $ ../path/to/bin/phantomjs extract-links.js 

Lingua: Coldfusion 9.0.1+

Libreria: jSoup

  function parseURL(required string url){ var res = []; var javaLoader = createObject("javaloader.JavaLoader").init([expandPath("./jsoup-1.7.3.jar")]); var jSoupClass = javaLoader.create("org.jsoup.Jsoup"); //var dom = jSoupClass.parse(html); // if you already have some html to parse. var dom = jSoupClass.connect( arguments.url ).get(); var links = dom.select("a"); for(var a=1;a LT arrayLen(links);a++){ var s={};s.href= links[a].attr('href'); s.text= links[a].text(); if(s.href contains "http://" || s.href contains "https://") arrayAppend(res,s); } return res; } //writeoutput(writedump(parseURL(url)));   

Restituisce una matrice di strutture, ogni struttura contiene un object HREF e TEXT.

Lingua: JavaScript / Node.js

Libreria: Richiesta e Cheerio

 var request = require('request'); var cheerio = require('cheerio'); var url = "https://news.ycombinator.com/"; request(url, function (error, response, html) { if (!error && response.statusCode == 200) { var $ = cheerio.load(html); var anchorTags = $('a'); anchorTags.each(function(i,element){ console.log(element["attribs"]["href"]); }); } }); 

La libreria di richieste scarica il documento html e Cheerio consente di utilizzare i selettori di jquery css per scegliere come target il documento html.